Angular-cli: ng build for i18n - set document locale

Created on 19 Oct 2017  路  16Comments  路  Source: angular/angular-cli

Bug Report or Feature Request (mark with an x)

- [] bug report
- [x] feature request

Versions.

@angular/cli: 1.4.4
node: 8.5.0
os: win32 x64
@angular/animations: 4.4.4
@angular/cdk: 2.0.0-beta.12
@angular/common: 4.4.4
@angular/compiler: 4.4.4
@angular/core: 4.4.4
@angular/forms: 4.4.4
@angular/http: 4.4.4
@angular/material: 2.0.0-beta.12
@angular/platform-browser: 4.4.4
@angular/platform-browser-dynamic: 4.4.4
@angular/router: 4.4.4
@angular/cli: 1.4.4
@angular/compiler-cli: 4.4.4
@angular/language-service: 4.4.4
typescript: 2.3.4

Repro steps.

Run a i18n build including the locale flag:

ng build --locale de.......

Then have a look at the index.html inside dist folder.
The document's locale is still set to <html lang="en"> when you build a locale "de".

This causes some browsers to suggest a translated version of the site and breaks built in spellcheckers.

The log given by the failure.

No log

Desired functionality.

The index.html in build results should contain a correct lang attribute.

<html lang="en">

Mention any other details that might be useful.

Nothing

devkibuild-angular help wanted 3 (nice to have) feature

Most helpful comment

since the cli injects the script files into the index, it would make sense if it could change the locale as well at the same time :)

All 16 comments

@ocombe is this functionality planned planned to be supported in core?

It is not, I've actually asked this a few days ago. The answer that I was given was:

You can use DOCUMENT to easily handle that, it works both on Universal and in browser without issue

documentElement is the <html> tag as an Element which means you can use all the normal methods like (get|remove|set)Attribute()

I would add that you should probably use Renderer2 to set the attribute on the documentElement.
Here is how I would do it, on the main component:

export class AppComponent {
  constructor(@Inject(DOCUMENT) doc: Document, @Inject(LOCALE_ID) locale: string, renderer: Renderer2) {
    renderer.setAttribute(doc.documentElement, 'lang', locale);
  }
}

I wonder if setting the lang in the app (after document ready) is working for screen readers and stuff like that though, it would probably be better if the cli could set it during compilation using the html webpack plugin ?
We could ask @marcysutton, she should know

@ocombe
At least this will not work for anything that is reading the document before angular has started.
So setting in in build would be much cleaner

Setting the lang during HTML compilation would indeed be better than client-side. It's one less thing for screen readers to wait for, although they do look at the accessibility tree as-rendered after scripting and styles have run.

Ok thanks!

Accessibility problems and I'm pretty sure setting the lang code during runtime is also an SEO problem for crawlers looking for meta tags like hreflang.
https://support.google.com/webmasters/answer/189077?hl=en

So unless you universal/prerender pages with directive you described, SEO for i18n'd applications _could suffer_.

I have this same request. @mbeckenbach, as a temporary workaround, you could create a script like this and run it after build:

`const replace = require('replace-in-file');
const langCodes = ['es', 'fr', 'hi', 'id', 'ru'];

function replaceAttributes() {
langCodes.forEach(code => {
const options = {
files: dist/${code}/index.html,
from: html lang="en",
to: html lang="${code}",
};

replace(options)
  .then(changes => {
    console.log('Modified file:', changes.join(', '));
  })
  .catch(error => {
    console.error('Error occurred:', error);
  });

})
}

replaceAttributes();`

As I'm currently fighting with angular i18n + pwa combo (a lot of things are broken, especially pre angular 8), wasted a lot of time with it.

If you also use (or plan to) @angular/pwa @jacobbowdoin 's solution will change the hashes of the dist index.html, which will actually lead you to the caching bug (Hash mismatch).

The solution would be to change the html lang before building the angular app.

As a workaround I just used the "index" parameter on the build configs, in angular.json, to change the "index.html" to a new one that has the appropriate tags.

"pt": {
  "aot": true,
  "outputPath": "dist/pt/",
  "i18nLocale": "pt",
  "i18nFile": "src/locale/pt/messages.xlf",
  "index": "src/locale/pt/index.html"
 }

So each localized build can have their own "index.html". Each "index.html" is just a copy/paste of the others, except you just change the html lang attribute. This is done pre-build so it solves the problems mentioned before.

@vibrunazo Thanks for the workaround, it's good but it's still problematic that you have to edit multiple index.html files if you want to change the favicons for example.

@ocombe Are there any news on this or will it probably be a feature of the new i18n that comes with ivy?

There's no news on this, it's not on the list of the new i18n that comes with ivy as far as I know (cc @petebacondarwin that handles it now)

I might not be understanding the scope of this request but it seems to me that it has nothing to do with Angular core... the request is that the index.html that is built (via ng build) has its <html lang="en"> element modified to use the specified locale. In that case it would seem that this would be a webpack plugin to include in the CLI. cc @filipesilva ?

since the cli injects the script files into the index, it would make sense if it could change the locale as well at the same time :)

Yes, we could replace the lang tag via a regex when building for that locale.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings