Skip to content

i18n ignore leading and trailing spaces #13114

Open

Description

@zh99998

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

now ng-xi18n will generate xliff including spaces, for example there is an element

    <p i18n>
        复制
    </p>

it will generate

        <source>
                    复制
                </source>

it's really weak to rely on spaces since they could changed Unintentionally or even by IDE reformat code.

Expected behavior

ignore leading and tailing spaces

Activity

  1. added
    area: i18nIssues related to localization and internationalization
    featureLabel used to distinguish feature request from other issues
    on Nov 28, 2016
  2. panuruj commented on Mar 6, 2017

    @panuruj

    The more serious issue is that the ID takes the white space into account, and the ID could change just because of a change in the white space (e.g. indentation). The change in the ID prevents an existing translation from being used. I know that there is a feature to manually override the ID, but it would great if the generated ID can be more stable.

    CC: @ocombe

  3. ocombe commented on Mar 6, 2017

    @ocombe
    Contributor

    We could probably ignore the leading and trailing spaces yes, that would actually decrease the number of duplicated translations when we do the extraction and make the translations easier to do (with some software it's hard to reproduce the line breaks/tabs when you translate).
    What do you think @vicb ?

  4. ocombe commented on Mar 20, 2017

    @ocombe
    Contributor

    Another issue due to this:

    <h4 i18n>
          {ids.length, plural,
            =0 {You have not selected any country yet.}
            =1 {You have selected the following country: }
            other {You have selected the following countries: }
          }
    </h4>

    will generate 2 messages after extraction:

    <messagebundle>
      <msg id="203167065070819173">
          <ph name="ICU"><ex>ICU</ex></ph>
        </msg>
      <msg id="5290485580948134395">{VAR_PLURAL, plural, =0 {You have not selected any country yet.} =1 {You have selected the following country: } other {You have selected the following countries: } }</msg>
    </messagebundle>

    because there are line breaks before and after the ICU expression. Removing them would fix this.

  5. vicb commented on Mar 21, 2017

    @vicb
    Contributor

    Something we should work on for the next major release

  6. Goodwine commented on Mar 21, 2017

    @Goodwine

    Another case that should be handled is that changing indentation affects the generated message id. I believe the message extractor should replace(/\s+/, ' ') (or something like that).

    In the examples below, a span tag is updated to be surrounded by a div tag, which doesn't change the visible contents and therefore should preserve the same id, but it doesn't.

    Example:

    <!-- initial version -->
    <span i18n>
      Some text.
      Another Text.
    </span>
    
    <!-- updated version -->
    <div>
      <span i18n>
        Some text.
        Another Text.
      </span>
    </div>

    These will generate something like:

    <!-- initial version -->
    <messagebundle>
      <msg id="123">
      Some text.
      Another Text.
    </msg>
    </messagebundle>
    
    <!-- updated version -->
    <messagebundle>
      <msg id="456">
        Some text.
        Another Text.
      </msg>
    </messagebundle>

    One would expect that the actual generated message trims whitespaces (as OP suggests), and also transforms multiple whitespaces into a single one:

    <messagebundle>
      <msg id="123">Some text. Another Text.</msg>
    </messagebundle>

    Of course there is this problem then when the text is surrounded by a <pre> tag or css white-space:pre*, which I don't know what's the best way to solve without adding additional attributes to the tag that has i18n. e.g. <span i18n="desc" i18n-keepws>

  7. changed the title [-]i18n ignore leading and tailing spaces[/-] [+]i18n ignore leading and trailing spaces[/+] on Apr 2, 2017
  8. ocombe commented on Sep 19, 2017

    @ocombe
    Contributor

    @pkozlowski-opensource do you think that we could make this work with your changes for whitespaces removal?

  9. Jacksunwei commented on Oct 27, 2017

    @Jacksunwei
    Contributor

    I'd like to echo on this proposal. It seems stripping consecutive spaces is a more common use case. We can use additionally suffix (i18n-keepws) to tell message extractor not to do so if needed.

  10. added this to the Backlog milestone on Jan 23, 2018
  11. pmccloghrylaing commented on Mar 20, 2018

    @pmccloghrylaing
    Contributor

    @Jacksunwei would the existing ngPreserveWhitespaces attribute be sufficient?

  12. 49 remaining items

  13. maplion commented on Nov 13, 2021

    @maplion

    @Goodwine agreed, which is why I prefer the second option: put your tags at the lowest level (no nested html) and manage it that way. The browser often ignores non-explicit spaces anyway.

  14. gestj commented on Jan 28, 2022

    @gestj

    Since I also was annoyed by the whitespaces & I don't have any <pre> like messages involved I just quickly added the following workaround to my project.

    I use a tiny little "hack" in order to clean the generated messages.xlf file after it was written by Angular CLI.
    Combined with a npm script I now have exactly what I want with a single command.

    Pimp it if needed depending on your use case.

    clean-generated-xlf.js

    const fs = require('fs');
    
    const messageFile = './<your-src-folder>/locale/messages.xlf';
    
    const content = fs.readFileSync(messageFile, 'utf8');
    
    fs.writeFileSync(messageFile, content
        .replaceAll(/\s<\/source>/g, '</source>')
        .replaceAll(/<source>\s/g, '<source>'));
    

    package.json

        ...
        "scripts": {
            ....
            "extract-i18n": "ng extract-i18n --output-path <your-src-folder>/locale && node clean-generated-xlf.js"
        }
    

    https://regex101.com/r/lhCFwL/1

  15. zkirill commented on Jun 20, 2022

    @zkirill

    For IntelliJ go to Settings | Editor | Code Style | HTML and inside Don't break if inline content add button and any other elements that may accidentally get a newline when you Reformat Code.

  16. ciriousjoker commented on May 14, 2023

    @ciriousjoker

    Any news? Is this on anyone's radar?

  17. PowerKiKi commented on May 15, 2023

    @PowerKiKi
    Contributor

    It's still a pain point for us. Without being able to use formatting tool (such as prettier) our template suffer quite a lot, unless we format manually which really is very 1990.

    I meant to create a PR a while ago, but never got around to it. Not sure when I'd have time in the foreseeable future.

    Also I was under the impression that the core team might want to resolve that themselve, instead of accepting a PR from the community. @petebacondarwin can you confirm or infirm that ?

  18. t-mish commented on Jun 27, 2023

    @t-mish

    Any news? I think Angular team should consider spending some time in refreshing the i18n part of the framework

  19. killStrikeFF commented on Nov 30, 2023

    @killStrikeFF

    We are waiting for this

  20. yuriy-sng commented on Feb 19, 2024

    @yuriy-sng

    Oh look, another popular long-standing Angular bug 🙃

  21. RenePapeKmd commented on Mar 8, 2024

    @RenePapeKmd

    Since I also was annoyed by the whitespaces & I don't have any \<pre\> like messages involved I just quickly added the following workaround to my project.

    I use a tiny little "hack" in order to clean the generated messages.xlf file after it was written by Angular CLI. Combined with a npm script I now have exactly what I want with a single command.

    Pimp it if needed depending on your use case.

    clean-generated-xlf.js

    const fs = require('fs');
    
    const messageFile = './<your-src-folder>/locale/messages.xlf';
    
    const content = fs.readFileSync(messageFile, 'utf8');
    
    fs.writeFileSync(messageFile, content
        .replaceAll(/\s<\/source>/g, '</source>')
        .replaceAll(/<source>\s/g, '<source>'));
    

    package.json

        ...
        "scripts": {
            ....
            "extract-i18n": "ng extract-i18n --output-path <your-src-folder>/locale && node clean-generated-xlf.js"
        }
    

    https://regex101.com/r/lhCFwL/1

    This solution works very well, but I had to add a plus to the two whitespace captures to replace i.e. repeated spaces.
    So \s should be \s+ like:

         .replaceAll(/\s+<\/source>/g, '</source>')
         .replaceAll(/<source>\s+/g, '<source>'));
    
  22. patrickuhlmann commented on Mar 27, 2024

    @patrickuhlmann

    We "fixed" the problem with the duplicate translations (with/without whitespace) by using prettier/eslint with the option https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting html-whitespace-sensitivity: strict. The resulting code had no whitespace in the tag content anymore.

  23. t-mish commented on Mar 27, 2024

    @t-mish
  24. NateRadebaugh commented on Oct 3, 2025

    @NateRadebaugh
    Contributor

    @JoostK @JeanMeche is this something that will ever be fixed or should work figure out some bad workarounds in user-land?

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

Metadata

Metadata

Labels

area: i18nIssues related to localization and internationalizationfeatureLabel used to distinguish feature request from other issuesfeature: under considerationFeature request for which voting has completed and the request is now under considerationstate: Needs Design

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions