Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relies too much on Visual Studio specific functionality #31694

Closed
MartinNr5 opened this issue Feb 5, 2024 · 17 comments · Fixed by #31706
Closed

Relies too much on Visual Studio specific functionality #31694

MartinNr5 opened this issue Feb 5, 2024 · 17 comments · Fixed by #31706

Comments

@MartinNr5
Copy link
Contributor

Description

Since Visual Studio Code is such an immensely popular editor I think it's a detriment that this article relies on functionality only available in Visual Studio. I can't create a "shared resource files with a Build Action of Embedded resource" in VS Code, and I can't right-click to create a new file.

Localization is confusing and complicated as it is to get right without having the reader also try to figure out how to perform Visual Studio specific activities in VS Code (or any other editor for that matter).

If localization of a Blazor app isn't possible without Visual Studio then that should be clearly noted at the start of the article.

Page URL

https://learn.microsoft.com/en-us/aspnet/core/blazor/globalization-localization?view=aspnetcore-8.0

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/globalization-localization.md

Document ID

d6f07538-228e-9f96-680f-6c324caf11d6

Article author

@guardrex

Copy link
Contributor

github-actions bot commented Feb 5, 2024

💘 Hello, February! Goodbye, New Year's resolutions! 😆

A green dinosaur 🦖 will be along shortly to assist. Stand-by ........

@guardrex
Copy link
Collaborator

guardrex commented Feb 5, 2024

Hello @MartinNr5 ... Yes, it's reasonable to look into this and see what we can do. I don't think anything in particular is blocked for VSC ... we just need the alternative guidance on what VSC devs should do. I propose that we pivot the whole topic between the two IDEs.

Note that we're experiencing a CRAZY 😵 high level of 8.0 doc churn right now. I'll schedule this for work, but I can tell you that it will take months to reach it for work under the current workload. I'm sorry about that, but the 8.0 release that introduced Blazor Web Apps and a focus on render modes over hosting models is taking quite a lot of work to resolve in the docs. I'm still working 8.0 issues with no end in sight yet 😅. I'll get back to this as soon as I can.

@MartinNr5
Copy link
Contributor Author

MartinNr5 commented Feb 5, 2024 via email

@Rick-Anderson
Copy link
Contributor

Rick-Anderson commented Feb 6, 2024

@MartinNr5 dup of #2501

@Rick-Anderson
Copy link
Contributor

@MartinNr5 thanks for bring this up. What do you think of this comment ?

@Rick-Anderson
Copy link
Contributor

@guardrex @MartinNr5 recommend closing as a dup.

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

Creating the files can be accomplished manually at least, if not via 3rd party tooling.

I'd like to study this a bit more. I'll get back to it as soon as I can.

@MartinNr5
Copy link
Contributor Author

MartinNr5 commented Feb 6, 2024 via email

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

It's a different article, which has to be updated separately by me, so this issue should be left open.

@MartinNr5
Copy link
Contributor Author

@guardrex Ah, apologies, I didn't notice that.

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

Unfortunately, the MS doc isn't helpful, as it just tells everyone to use VS ...

https://learn.microsoft.com/dotnet/core/extensions/create-resource-files

I noticed that Tim Heuer, a MS PM, has an editor for VSC in the marketplace ...

We can recommend it because he's a MS 🐱. There are a few others that devs can explore ...

https://marketplace.visualstudio.com/search?term=resx&target=VSCode&category=All%20categories&sortBy=Relevance

The problem I foresee with these is that not all of them look like they can create the .resx file to begin with. I'll load up Tim's extension and see if it can create the base file. He doesn't document it, but it might be there.

One I see seems to have a snippet feature for a new file ...

@hishamco ... Do you know what tooling is common for devs to use to create/edit .resx files in Visual Studio Code? Seven years ago this SO answer said it couldn't be done in VSC directly ...

https://stackoverflow.com/questions/40953193/vs-code-resx-file-extension

... and BTW ... I'm assuming that the rest of the loc infrastructure works correctly without any other steps (e.g., resgen.exe is run on the files to produce the correct binaries, etc.).

@MartinNr5
Copy link
Contributor Author

@guardrex Resgen isn't mentioned in the doc page I'm referring to in this issue, and only as a reference in the overview of the Globalization and localization of a .Net application so I didn't personally know I had to use it.

It's never mentioned as a required step in any of the documentation I read on how to localize a .Net application. It might be mentioned in other documentation, but not in the one I found. Reading up on the subject I guess this is what Visual Studio does when you create a .resx file, maybe?

I generally think that the current approach to localize a .Net application is convoluted and fiddly, but that's not an issue the documentation team can solve. :)

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

I think resgen.exe is built-into the runtime somehow, but I don't know for sure. I don't know if a separate step would be required for VSC devs or not. Hisham probably knows more about that aspect and may have general, direct knowledge on what VSC devs do professionally with VSC and loc.

I'm willing to run a few tests here, but I'm bogged down in 8.0 work right now, so I'll get back to this as soon as I can. I might be able to look later today or tomorrow. For now, I look forward to any information that Hisham can provide.

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

I have a few minutes here 🏃😅, so I checked out our Localization section guidance using Tim's ResX Editor extension.

The extension works ok, but I was a bit put off by one thing: You must add your loc entries, save the .resx file, close it, and then re-open the file to see the resource data data. I wish it would somehow save and update the UI immediately on-the-fly for every resource added to the file. Anyway ... that part ... the use of the extension was fine for not having to fiddle with all of that XML code and manually change lines in such a file. One merely adds an empty .resx file to the app, and the extension takes over from there. The en-us base file that I created with the extension was created for me with the following content ...

<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema

    Version 2.0

    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.

    Example:

    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>

    There are any number of "resheader" rows that contain simple
    name/value pairs.

    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.

    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:

    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.

    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0"/>
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string"/>
              <xsd:attribute name="type" type="xsd:string"/>
              <xsd:attribute name="mimetype" type="xsd:string"/>
              <xsd:attribute ref="xml:space"/>
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string"/>
              <xsd:attribute name="name" type="xsd:string"/>
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
              <xsd:attribute ref="xml:space"/>
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required"/>
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="Greeting" xml:space="preserve">
    <value>Hello, World!</value>
    <comment>None</comment>
  </data>
</root>

So far, so good. The key-value pair of that matches what I show in the raw file in the article, except the extension-generated file adds the comment metadata. This is from the article for comparison ...

<data name="Greeting" xml:space="preserve">
  <value>Hello, World!</value>
</data>

Then .....

💥

... well ... it doesn't fail with an error, it just no-ops. Using the component from the article, it results in just the key "Greeting" rendered in the component ...

image

I'll work with it a bit more and see if I can spot an obvious problem.

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

Ah, ha!!! 🐮👅 LICK'D IT!!!!!!

So, it turns out that the resource files need to be in the Pages folder SxS with the component. When I merely moved the files from the root of the app to the Pages folder ...

image

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

... and it works in Spanish if the browser's language is changed ...

image

@guardrex
Copy link
Collaborator

guardrex commented Feb 6, 2024

Ok ... I have enough information now to fix this issue.

I'll recommend Tim's extension SxS with the VS remark. I won't go to the trouble of pivoting the whole article. That's overkill.

@hishamco ... I think it's a false alarm on a basic use case for VSC. I'll ping you for review on the PR when it goes up in a few minutes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants