Resx in Blazor WASM: What is "the issue" with the old static way of using the Resx Files? - localization

[Disclaimer: I'm a long-time Desktop developer slowly learning Web and Blazor, so might be a noob question] but,
How come, when you try to find best-practice for doing Localization in Blazor you are told from official MS Docs (https://learn.microsoft.com/en-us/aspnet/core/blazor/globalization-localization?view=aspnetcore-5.0&pivots=webassembly) and various blogs to do the following:
Add NuGet Package: Microsoft.Extensions.Localization
Register localization "builder.Services.AddLocalization();"
Add your resx Files
Make IStringLocalizer (#inject IStringLocalizer Loc)
And finally use the following in your razor pages: #Loc["Greeting"]
Sure above works, but to a Desktop developer, this feels like a massive step-back in quality and "refactor-safeness" and the new way to use "magic strings" to reference the translations.
I've tested, and the "old way" on a Blazor Page of just:
Adding a MyResource.resx
Let it use the custom tool "PublicResXFileCodeGenerator" to make the .designer file
Simply reference the translation using MyResource.MyTranslationKey;
It works, it is refactor-safe, no need for an injection or NuGet packages... It just works, but despite that, it is not the recommended way... My question is why not? What is the drawback (all the blog and documentation fail to say why the new way is better)

I think there are a number of disadvantages using PublicResXFileCodeGenerator, which may have led to the current recommendations on how to support i18n-capabilities in [blazor-]apps.
Note that this is just a list of reasons I personally came up with finding possible causes which may have led to the current recommendations:
A: Visual Studio exclusivness
The way how PublicResXFileCodeGenerator generates files seem to be VisualStudio exclusive. Today´s teams tend to use a variety of IDEs / editor to build software, (f.e. VS, VSCode, Rider, WebStorm, etc.).
At least from my perception over the last couple of years
using IStringLocalizer works for all editors, even notepad or vim.
B: no default fallback
With the recommended way of accessing a translation, there will always be a useful fallback which is provided in markup. That is not the case when using the generated types to access translation-units.
C: no builtin-support for interpolation
Using IStringLocalizer, there is a built-in, lightweight and formalized way for utilizing interpolated strings. It even encourages using such strings in favor of manually building together such values, which is considered bad-practice when translating software.
DO:
#inject IStringLocalizer<DemoPage> L
<h1>#L["Greetings, {0}", userName]</h1> <!--Greetings, Arthur-->
#code {
string userName = "Arthur";
}
DON´T:
<h1>#DemoPageRessources.Greeting #userName</h1> <!--Greetings Arthur-->
#code {
string userName = "Arthur";
}
this dictates the order of strings, which might be OK for one language, but not for another. Achieving this with the generated type is a bit more verbose, and even may lead to runtime-exceptions, when there is no actual translation, i guess.

Related

Refactoring features for ASP.NET Core on VS 2017 are not working very well for me… Am I doing something wrong?

I am in the process of learning ASP.NET Core MVC, while experimenting, I noticed that when I try to refactor the code using the built in refactoring tools provided by Visual Studio they don't work very well. For example:
Renaming a class via the solution explorer pane usually fails. When it succeeds it will fail to rename the class on the view declaration (eg: #model ClassNameIsNotRenamed);
If I rename a controller or action, the helper tags such as asp-controller="NotRenamed" and asp-action="NotRenamed" do not get updated.
etc.
I don't want to get too detailed on what works and what does not work, the point that I am trying to make is that VS 2017 does not appear to do a good job when it comes to refactoring.
So my question is... Am I asking to much from VS 2017? Is there something that I can do to make refactoring work better?
Thanks.
Doing something like a rename requires that your project can build successfully. If you attempt rename something like a class, and the project either hasn't been built or failed the build, the rename will fail as well. This is fairly logical, as doing a rename refactor requires tracking references, which it can't do without the IL.
As far as your Razor views and controller/action references go, you're dealing with strings and/or code that is not compiled. As a result, it doesn't participate in code-based refactoring generally. Certain things like renames give you option to search strings as well, which you can do to catch more places where things should be renamed, such as your controller/action references. However, that can also cause unwanted side effects if you happen to be using the same string somewhere else, in a different context (which is why string replacement is not done by default).

How to identify what projects have been affected by a code change

I have a large application to manage consisting of of three or four executables and as many as fifty .dlls. Many of the source code files are shared across many of the projects.
The problem is a familiar one to many of us - if I change some source code I want to be able to identify which of the binaries will change and, therefore, what it is appropriate to retest.
A simple approach would be simply to compare file sizes. That is an 80% acceptable solution, but there is at least a theoretical possibility of missing something. Secondly, it gives me very little indication as to WHAT has changed; It would be ideal to get some form of report on this so I can then filter out irrelevant (e.g. dates/versions copyrights etc..)
On the plus side :
all my .dcus are in a row - I mean they are all built into a single folder
the build is controlled by a script (.bat)(easy, for example, to emit .obj files if that helps)
svn makes it easy to collect together any (two) revisions for comparison
On the minus side
There is no policy to include all used units in all projects; some units get included because they are on a search path.
Just knowing that a changed unit is used/compiled by a project is not sufficient proof that the binary is affected.
Before I begin writing some code to solve the problem I would like to ask the panel what suggestions they might have as to how to approach this.
The rules of StackOverflow forbid me to ask for recommended software, but if anyone has any positive experiences of continuous integration tools that would help - great
I am open to any suggestion or observation that is relevant in this context.
It seems to me that your question boils down to knowing which units are contained in your various executables. Since you are using search paths, it will be hard for you to work this out ahead of time. The most robust way to find out is to consult the .map file that the compiler emits. This contains a list of all units contained in your executable.
Once you know which units are contained in each executable, you need to know whether or not anything has changed in those units. That information is contained in your revision control system. Put this all together and you have the information that you need.
Of course, just because the source code for a unit has changed, you might argue that re-testing is not needed. Perhaps the only change made was the version, or the date in a copyright label or some such. But it is asking too much to be able to ask a computer to make such a judgement. At some point you need a human to step up and take responsibility.
What is odd about this though is that you are asking the question at all. It seems to me to be enormously risky to attempt partial testing. I cannot understand why you don't simply retest the entire product.
After using it for > 10 years for commercial in-house and freelancer work in large projects, I can recommend to try Apache Ant. It is a build tool which supports dependencies, and has many very helpful features.
Apache Ant also integrates nicely with CI tools such as Hudson/Jenkins, Bamboo etc.
Another suggestion - based on experience with Maven - is to design the general software architecture as modular as possible. If modules (single or multiple source or DCU files in one directory) use a version number in the directory name as a version number, it is possible to control exactly how application are composed from these modules.
If you want to program such a tool yourself the approach would be something like this:
First you need to detect wheter there were any changes made to seperate source files. As you already figured out comparing the file size is bad idea as the file size can stay the same despite lots of changes made to it (as long as there is same amount of text in pas file its size won't change). So instead you could check the last modification time for specific file or create some hash value like MD5 hash for comparison (can be quite slow).
Then you need to generate yourself a dependancy tree which will tell you which files are used for which project/subproject.
Finally based on changes detected in seperate files you check the dependancy tree to see which projects needs to be recompiled.
The problem of such approach is that you would probably have to update the dependancy tree manually each time when new unit is added to the project or an existing one is removed from the project.
But the best way would be to go and use some version controll software istead of reinventing the wheel. I myself like the way how GIT works and I belive that with proper implementation of GIT into the project mannager itself could be quite powerfull do to GIT support of branching/subbranching (each project is its own branch, each version of your software can be its own subbranch).
Now latest version of Delphi does have GIT integration done though SVN but this unfortunately limits some of best GIT functionality. So if you maybe decide to go and integrate GIT support directly into Delphi I'm first in line to use it.

Find differences in a .po file

I have a .po file where most translated strings are identical to original ones. However, few are different. How do I quickly find the ones that differ from original?
use podiff
I used it, an it workd for me. Its in C, so you have to compile it. make is your friend
I would suggest using one of the many web-based localization management platforms. To name a few:
Amanuens (disclaimer: my company builds this product)
Web Translate It
Transifex
GetLocalization
This kind of platforms allows you to keep your resource files in sync, edit them in a web-based editor (useful for no-technical translators) and most importantly to highlight/see only the changed/untranslated strings.

spring.codeconfig vs xml configuration

I've been using spring.net with xml configuration for some times, and I just saw that spring team released CodeConfig a month ago.
What I like about the xml config is that if I have a problem on the live server I can easily change the xml configuration to enable some specific debugging settings, or disable a specific component simply changing the xml configuration.
What is the advantage of using a code configuration instead of an xml configuration other than compile time check?
With code config, possible benefits you could get are:
Better refactoring support; e.g. renaming an injected property
More compact configuration, compared to xml
Developers can use code, in which they are often more at home than in xml
Benefit of the last point is also that developers new to the framework will have a significantly less steep learning curve than with the xml config.
From the docs:
While there are several positive
aspects to expressing configuration
metadata in XML files, there are also
many problems with this approach
including the verbosity of XML and its
heavy dependence on string-literals
which are both prone to typing errors
and unusually resistant to most modern
refactoring tools in use today. The
CodeConfig approach removes these
problems by providing a type safe,
code-based, approach to dependency
injection. It keeps the configuration
metadatda external to your class so
your class can be a POCO, free of any
DI related annotations.
Just to highlight one thing, you can mix and match configuration styles. From within a CodeConfig class you can refere to XML config files using the [ImportResource] attribute (see here), and in the XML you can use the namespace (see here).
Cheers,
Mark

Visual Studio: What approach do you use to 'template' plumbing for similar projects?

When building ASP.NET projects there is a certain amount of boilerplate, or plumbing that needs to be done, which is often identical across projects. This is especially the case with MVC and ALT.NET approaches. [I'm thinking of things such as: IoC, ORM, Solution structure (projects), Session Management, User Management, I18n etc.]
I would like to know what approach you find best for 'reusing' this plumbing across projects?
Have a 'master solution' which you duplicate and rename somehow? (I'm using a this to a degree at the moment, but it's fairly messy. Would be interested how people do this 'better')
Mainly rely on Shared Library projects? (I find this appropriate for some things, but too restrictive for things that have to be customised)
Code generation tools, such as T4? (Similar to the approach used by SharpArchitecture - have not tried this myself)
Something else?
Visual Studio supports Custom Templates.
I definitely (mostly!) go for T4 templates in conjunction with a modified version of SubSonic 3. I kind of use the database to model my domain and then use the T4 templates to generate the model and associated controllers and views. It takes about 50-60% of the effort out and keeps a consistency in place.
I then work on overrides (partials) of the classes along with filters and extension methods to 'make the app'. Now that I'm familiar with the environment and what I'm doing, I can have a basic model with good plumbing in place in a very short space of time. More importantly, because I create a set of partial class files, I can regenerate all I want without losing any of my 'custom' coding.
It works for me anyway :)
You could do it the bearded, t-shirted, agile style and create a nice template and put it in sourcecontrol. So when you need a new project, you just checkout the template?
For insanely fast MVC site setup, I use modified T4 templates (created with T4 Editor) and with ALOT of help from Oleg Sych's blogs for page generation (for your typical add/edit/index pages) combined with an awesome implementation of an automated create-update-delete called MVCCrud (if LINQ-to-SQL is your preferred data access method)
Using modified T4 templates and MVCCrud you can create fully functional entities (Create/Edit/List/Delete) with error handling and intuitive error messages in about 4 minutes for each.
I create a new project using the new project wizard so that I get unique project GUIDs assigned. Then I would use "Add Existing Item" to copy items from similar projects if it made sense to do so.
I sometimes use a file diff tool to copy references from one project to another, otherwise I just add the references by hand. A file diff tool can also be used to include similar source files, but the underlying files have to be copied anyway, so I prefer "Add Existing Item".
I've used T4 to generate solution and project files, but that definitely seems like an edge case and not something that would normally be necessary. In that case, I'd probably wrap the T4 in a PowerShell like script to create and populate the rest of the directory structure.
I use "shared libraries" pretty aggressively in general, but not specifically due to this scenario.
In general, I don't find myself reusing plumbing between projects much. It's probably more often that I hack away in one "prototype" project, then abandon it, and rebuild the project from scratch following the above approach and only bring over the "non-hacky" code.
I'm creating a MVC2 application template at http://erictopia.com. It will contain all the basic items I think should be in a MVC project. These include BDD specifications, an ORM (NHibernate and possibly Lightspeed), T4 templates, custom providers, ELMAH support, CSS/Javascript minifier, etc.

Resources