jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.44k stars 4.02k forks source link

New application without internationalization is always in English #15964

Closed vitoraasouza closed 2 years ago

vitoraasouza commented 3 years ago
Overview of the issue

When we create a new application, without choosing internationalization support and we select a native language other than English, the result is a front end in English. It is worth noting that in the .yo-rc.json file (presented below) the field nativeLanguage is correctly assigned with the native language selected (pt-br), whereas the field languages contains ["en", "fr"].

Motivation for or Use Case

According to JHipster generator, it seems that the resulting application will show up in the native language chosen, disregarding the internationalization.

Reproduce the error
Related issues

.

Suggest a Fix

.

JHipster Version(s)
test-n-oi-18-n@0.0.1-SNAPSHOT /home/shiryu/Desktop/tests/testNOi18n
└── generator-jhipster@7.1.0
JHipster configuration, a .yo-rc.json file generated in the root folder
.yo-rc.json file
{
  "generator-jhipster": {
    "applicationType": "monolith",
    "baseName": "testNOi18n",
    "jhipsterVersion": "7.1.0",
    "skipClient": false,
    "skipServer": false,
    "skipUserManagement": false,
    "skipCheckLengthOfIdentifier": false,
    "skipFakeData": false,
    "jhiPrefix": "jhi",
    "entitySuffix": "",
    "dtoSuffix": "DTO",
    "testFrameworks": [],
    "blueprints": [],
    "otherModules": [],
    "pages": [],
    "creationTimestamp": 1628867582797,
    "serviceDiscoveryType": false,
    "reactive": false,
    "authenticationType": "jwt",
    "packageName": "test.no.i18n",
    "serverPort": "8080",
    "cacheProvider": "ehcache",
    "enableHibernateCache": true,
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "prodDatabaseType": "postgresql",
    "buildTool": "gradle",
    "serverSideOptions": [],
    "websocket": false,
    "searchEngine": false,
    "messageBroker": false,
    "enableSwaggerCodegen": false,
    "clientFramework": "angularX",
    "withAdminUi": false,
    "clientTheme": "none",
    "enableTranslation": false,
    "nativeLanguage": "pt-br",
    "packageFolder": "test/no/i18n",
    "jwtSecretKey": "YourJWTSecretKeyWasReplacedByThisMeaninglessTextByTheJHipsterInfoCommandForObviousSecurityReasons",
    "devServerPort": 4200,
    "clientPackageManager": "npm",
    "clientThemeVariant": "",
    "languages": ["en", "fr"]
  }
}

JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory
JDL entity definitions

Environment and Tools

openjdk version "11.0.11" 2021-04-20 OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.16.04) OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.16.04, mixed mode, sharing)

git version 2.32.0

node: v14.17.4

npm: 7.20.3

Docker version 20.10.7, build f0df350

docker-compose version 1.28.6, build 5db8d86f

Browsers and Operating System

OS: Ubuntu 16.04.7 LTS Browser: Google Chrome Version 92.0.4515.107 (Official Build) (64-bit)

gmarziou commented 3 years ago

According to JHipster generator, it seems that the resulting application will show up in the native language chosen, disregarding the internationalization.

Where did you read that?

If you look at Angular home template file in generator, you'll see that English texts are hard coded.

To support this we should use nodejs templates, I did an experiment 2 years ago but I never finished. The idea was to run a script to transform all ejs templates from current:

<h1 jhiTranslate="activate.title">Activation</h1>

to

<h1 jhiTranslate="activate.title"><%- t('activate.title') %></h1>
Tcharl commented 3 years ago

Another annoying part are the response sent by the API (error or ack messages)

mshima commented 3 years ago

I created https://github.com/jhipster/generator-jhipster/pull/15969. It will allow to inject translations into templates if someone wants to contribute.

vitoraasouza commented 3 years ago

Where did you read that?

@gmarziou, maybe I misunderstood the concept of native language in this context, but in the way that the following questions are asked, I was hoping that the resulting application was delivered with the selected language.

Screenshot from 2021-08-16 11-40-28

By the way, when we answer yes to internationalization and select only one language (the native one), the resulting application is presented in this language. Considering this behavior, perhaps just a modification during the generation is sufficient to solve this issue. The possible solution would be: for applications without internationalization, the flow of its creation should be the same as an application with internationalization with a single language selected.

If you look at Angular home template file in generator, you'll see that English texts are hard coded.

I didn't know that. I thought these hard coded parts would be replaced by translated texts and, because of this, jhiTranslate attributes would not be used.

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 30 days with no activity. Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted. We are accepting PRs :smiley:. Comment or this will be closed in 7 days

deepu105 commented 2 years ago

This is not supported by design, I think the prompt showing up could be a regression, when you disable i18n there shouldn't be a language selection prompt AFAIR. IMO its a lot of work to do this properly at the moment so unless someone is willing to con tribute this I think we wont do this

mshima commented 2 years ago

Let's keep this open. Api to implement this is ready, just need to customize the templates:

Take: https://github.com/jhipster/generator-jhipster/blob/980ca577b72a846208d2fec0d85267a995bc8e53/generators/client/templates/angular/src/main/webapp/app/home/home.component.html.ejs#L27

<p class="lead" <%= jhiPrefix %>Translate="home.subtitle">This is your homepage</p>

Should be replaced by: <p class="lead" <%= jhiPrefix %>Translate="home.subtitle"><%- this._getClientTranslation('home.subtitle') %></p>

this._getEntityClientTranslation should be used for entities.

LalaRzayeva commented 2 years ago

I'll take care of it next week if no one minds.

LalaRzayeva commented 2 years ago

@mshima @deepu105 I've already updated most of the templates, but I'm running into some issues that you might be able to help me solve.

1. getClientTranslation does not seem to find translations for keys containing dots. For example, I get Translation missing for metrics.refresh.button because it is defined like this:

{
    "metrics": {
        "refresh.button": "Refresh"
    }
}

And there are quite a few translation keys with this problem.

2. Some translations require specific values, but as far as I can see there is no support for this in the new API. For example, passwords.title expects username to be passed which is interpolated from account.login and which is also used in the hardcoded text:

<h2 <%= jhiPrefix %>Translate="password.title" [translateValues]="{ username: account.login }">
  Password for [<strong>{{account.login}}</strong>]
</h2>

But replacing it with <%- this._getClientTranslation('password.title') %> gives us Password for [<strong>{{username}}</strong>] in generated component which would not work since we do not have username.

3. Some translation tags contain expressions, such as {{ 'health.status.' + componentHealth.value!.status }} or <%= i18nKeyPrefix %>.home.title, which I could not make work with the new method.

<%- this._getClientTranslation("{{ 'health.status.' + componentHealth.value!.status }}") %> is not evaluated and I get Translation missing for {{ 'health.status.' + componentHealth.value!.status }} <%- this._getEntityClientTranslation('<%= i18nKeyPrefix %>.home.title') %> fails on generation with [Error: Could not find matching close tag for "<%-".]

4. In some places I noticed conditions checking if translation is enabled, for example:

<%_ if (enableTranslation) { _%>
    <div <%= jhiPrefix %>Translate="global.item-count" [translateValues]="{ first: first, second: second, total: total }"></div>
<%_ } else { _%>
    <div>Showing {{ first }} - {{ second }} of {{ total }} items.</div>
<%_ } _%>

or

<label class="form-label" <%= jhiPrefix %>Translate="<%= translationKey %>" for="field_<%= fieldName %>"<% if (field.javadoc) { if (enableTranslation) { %> [ngbTooltip]="'<%= i18nKeyPrefix %>.help.<%= fieldName %>' | translate"<% } else { %> ngbTooltip="<%= field.javadoc %>"<% } } %>><%= fieldNameHumanized %></label>

and it is not entirely clear how to handle such cases, especially the last one which, in my opinion, is not readable at all.

mshima commented 2 years ago

@LalaRzayeva that's great.

  1. I think you can use this._getTranslation('metrics["refresh.button"]'). It uses lodash get internally.

  2. I need to take a look. In this case we will need to make the component api to match the template. https://github.com/jhipster/generator-jhipster/blob/e471bf35d70513e90d4ad01fe99f434cae6451bc/generators/languages/templates/src/main/webapp/i18n/en/password.json#L2-L3 username at the component needs get the account.login value.

  3. There are 2 situations

    • {{ 'health.status.' + componentHealth.value!.status }}" is dynamic may need individual evaluation.
    • <%- this._getEntityClientTranslation('<%= i18nKeyPrefix %>.home.title')%> to <%- this._getEntityClientTranslation(i18nKeyPrefix + '.home.title')%>
  4. Same as 2., need to be evaluated each case.

You may add a link to each case to make easier to evaluate.

LalaRzayeva commented 2 years ago

Thanks for the tips @mshima, I'll update what I can and add links to other cases.

mshima commented 2 years ago

<div>Showing {{ first }} - {{ second }} of {{ total }} items.</div> should be identical to the result of <div><%- this._getEntityClientTranslation('global.item-count')%></div> https://github.com/jhipster/generator-jhipster/blob/e471bf35d70513e90d4ad01fe99f434cae6451bc/generators/languages/templates/src/main/webapp/i18n/en/global.json.ejs#L109

LalaRzayeva commented 2 years ago

@mshima I also have a problem using _getEntityClientTranslation, maybe I'm missing something, but I thought that it should be used in all templates in entity-client directory but I get Translation missing for entity.action.cancel when use <%- this._getEntityClientTranslation('entity.action.cancel') %>. Should I use _getClientTranslation instead and in which case should _getEntityClientTranslation be used then?

mshima commented 2 years ago

@LalaRzayeva _getEntityClientTranslation should be used when the key is specific to the entity. Normally it starts with i18nKeyPrefix. eg i18nKeyPrefix + .home.createOrEditLabel.

mshima commented 2 years ago

Realized that _getClientTranslation is missing at entity-client.

mshima commented 2 years ago

You may add a dumb function at entity-client generator for now:

  _getClientTranslation(translationKey) {
    return "TODO Implement clientTranslation";
  }
LalaRzayeva commented 2 years ago

@mshima I created a draft PR, replacing everything I could following your suggestions, and in the last commit I marked all the problem areas with TODO: 15964 comments for you to take a look.