aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.41k stars 2.12k forks source link

I18n `setDefaultLanguage` is never called (v6) #12767

Closed milotoor closed 8 months ago

milotoor commented 8 months ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication, Internationalization

Amplify Categories

auth

Environment information

``` System: OS: macOS 14.0 CPU: (10) arm64 Apple M2 Pro Memory: 63.00 MB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node npm: 10.2.3 - ~/.nvm/versions/node/v20.10.0/bin/npm Browsers: Chrome: 120.0.6099.129 Safari: 17.0 npmPackages: @actions/core: ^1.10.1 => 1.10.1 @actions/github: ^6.0.0 => 6.0.0 @ampproject/toolbox-optimizer: undefined () @aws-amplify/ui-react: ^6.0.7 => 6.0.7 @aws-amplify/ui-react-internal: undefined () @aws-sdk/client-secrets-manager: ^3.480.0 => 3.480.0 @babel/core: undefined () @babel/runtime: 7.22.5 @casl/ability: ^6.5.0 => 6.5.0 @casl/ability/extra: undefined () @casl/react: ^3.1.0 => 3.1.0 @datadog/browser-rum: ^5.4.0 => 5.4.0 @edge-runtime/cookies: 4.0.2 @edge-runtime/ponyfill: 2.4.1 @edge-runtime/primitives: 4.0.2 @emotion/cache: ^11.11.0 => 11.11.0 @emotion/react: ^11.11.3 => 11.11.3 @emotion/server: ^11.11.0 => 11.11.0 @emotion/styled: ^11.11.0 => 11.11.0 @fontsource/open-sans: ^5.0.18 => 5.0.18 @fontsource/titillium-web: ^5.0.17 => 5.0.17 @googlemaps/js-api-loader: ^1.16.2 => 1.16.2 @hapi/accept: undefined () @hookform/resolvers: ^3.3.2 => 3.3.2 @hookform/resolvers/ajv: 1.0.0 @hookform/resolvers/arktype: 1.0.0 @hookform/resolvers/class-validator: 1.0.0 @hookform/resolvers/computed-types: 1.0.0 @hookform/resolvers/io-ts: 1.0.0 @hookform/resolvers/joi: 1.0.0 @hookform/resolvers/nope: 1.0.0 @hookform/resolvers/superstruct: 1.0.0 @hookform/resolvers/typanion: 1.0.0 @hookform/resolvers/typebox: 1.0.0 @hookform/resolvers/valibot: 1.0.0 @hookform/resolvers/vest: 1.0.0 @hookform/resolvers/yup: 1.0.0 @hookform/resolvers/zod: 1.0.0 @mapbox/mapbox-gl-draw: ^1.4.3 => 1.4.3 @mapbox/mapbox-gl-style-spec: 14.0.0 @mswjs/interceptors: undefined () @mui/icons-material: ^5.15.0 => 5.15.0 @mui/lab: ^5.0.0-alpha.156 => 5.0.0-alpha.156 @mui/material: ^5.15.0 => 5.15.0 @mui/system: ^5.15.0 => 5.15.0 @mui/x-data-grid-premium: ^6.18.4 => 6.18.4 @mui/x-date-pickers-pro: ^6.18.2 => 6.18.2 @napi-rs/triples: undefined () @next/font: undefined () @next/react-dev-overlay: undefined () @opentelemetry/api: undefined () @reduxjs/toolkit: ^2.0.1 => 2.0.1 @reduxjs/toolkit-query: 1.0.0 @reduxjs/toolkit-query-react: 1.0.0 @reduxjs/toolkit-react: 1.0.0 @rollbar/react: ^0.11.2 => 0.11.2 @rtk-query/codegen-openapi: ^1.2.0 => 1.2.0 @segment/ajv-human-errors: undefined () @testing-library/react: ^14.1.2 => 14.1.2 @testing-library/user-event: ^14.5.1 => 14.5.1 @trivago/prettier-plugin-sort-imports: ^4.3.0 => 4.3.0 @turf/bbox: ^6.5.0 => 6.5.0 @turf/centroid: ^6.5.0 => 6.5.0 @turf/helpers: ^6.5.0 => 6.5.0 @types/autosuggest-highlight: ^3.2.3 => 3.2.3 @types/glob: ^8.1.0 => 8.1.0 @types/google.maps: ^3.54.10 => 3.54.10 @types/jsonwebtoken: ^9.0.5 => 9.0.5 @types/lodash: ^4.14.202 => 4.14.202 @types/mapbox__mapbox-gl-draw: ^1.4.6 => 1.4.6 @types/node: ^20.10.3 => 20.10.3 (14.18.63) @types/nprogress: ^0.2.3 => 0.2.3 @types/prismjs: ^1.26.3 => 1.26.3 @types/react: ^18.2.43 => 18.2.43 @types/react-datepicker: ^4.19.3 => 4.19.3 @types/react-draft-wysiwyg: ^1.13.7 => 1.13.7 @types/react-redux: ^7.1.33 => 7.1.33 @typescript-eslint/eslint-plugin: ^6.14.0 => 6.14.0 @typescript-eslint/parser: ^6.12.0 => 6.13.2 @vercel/nft: undefined () @vercel/og: 0.5.15 @vitejs/plugin-react: ^4.2.0 => 4.2.1 acorn: undefined () amphtml-validator: undefined () anser: undefined () apexcharts: ^3.44.0 => 3.44.2 arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () autosuggest-highlight: ^3.3.4 => 3.3.4 aws-amplify: ^6.0.9 => 6.0.9 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () babel-packages: undefined () browserify-zlib: undefined () browserslist: undefined () buffer: undefined () bytes: undefined () ci-info: undefined () cli-select: undefined () client-only: 0.0.1 clipboard-copy: ^4.0.1 => 4.0.1 clsx: ^2.0.0 => 2.0.0 comment-json: undefined () compression: undefined () conf: undefined () constants-browserify: undefined () content-disposition: undefined () content-type: undefined () cookie: undefined () cross-spawn: undefined () crypto-browserify: undefined () css.escape: undefined () data-uri-to-buffer: undefined () date-fns: ^2.30.0 => 2.30.0 debug: undefined () devalue: undefined () domain-browser: undefined () edge-runtime: undefined () eslint: ^8.54.0 => 8.55.0 eslint-config-next: ^14.0.3 => 14.0.3 eslint-config-prettier: ^9.0.0 => 9.1.0 eslint-import-resolver-alias: ^1.1.2 => 1.1.2 eslint-import-resolver-typescript: ^3.6.1 => 3.6.1 eslint-plugin-eslint-comments: ^3.2.0 => 3.2.0 eslint-plugin-import: ^2.29.0 => 2.29.0 events: undefined () find-cache-dir: undefined () find-up: undefined () fresh: undefined () geojson: ^0.5.0 => 0.5.0 get-orientation: undefined () glob: undefined () gzip-size: undefined () http-proxy: undefined () http-proxy-agent: undefined () https-browserify: undefined () https-proxy-agent: undefined () i18next: ^23.7.6 => 23.7.7 i18next-browser-languagedetector: ^7.2.0 => 7.2.0 i18next-http-backend: ^2.4.2 => 2.4.2 icss-utils: undefined () ignore-loader: undefined () image-size: undefined () is-animated: undefined () is-docker: undefined () is-wsl: undefined () jest-worker: undefined () jsdom: ^23.0.1 => 23.0.1 json5: undefined () jsonwebtoken: undefined () keen-slider: ^6.8.6 => 6.8.6 loader-runner: undefined () loader-utils: undefined () lodash: ^4.17.21 => 4.17.21 lodash.curry: undefined () lru-cache: undefined () mapbox-gl: ^3.0.1 => 3.0.1 micromatch: undefined () mini-css-extract-plugin: undefined () msw: ^2.0.9 => 2.0.10 mui-tel-input: ^5.0.0 => 5.0.0 nanoid: undefined () native-url: undefined () neo-async: undefined () next: ^14.0.3 => 14.0.3 node-fetch: undefined () node-html-parser: undefined () nprogress: ^0.2.0 => 0.2.0 ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () platform: undefined () postcss-flexbugs-fixes: undefined () postcss-modules-extract-imports: undefined () postcss-modules-local-by-default: undefined () postcss-modules-scope: undefined () postcss-modules-values: undefined () postcss-preset-env: undefined () postcss-safe-parser: undefined () postcss-scss: undefined () postcss-value-parser: undefined () prettier: ^3.1.1 => 3.1.1 (2.8.8) prismjs: ^1.29.0 => 1.29.0 process: undefined () punycode: undefined () querystring-es3: undefined () raw-body: undefined () react: ^18.2.0 => 18.2.0 react-apexcharts: ^1.4.1 => 1.4.1 react-builtin: undefined () react-datepicker: ^4.23.0 => 4.24.0 react-dom: ^18.2.0 => 18.2.0 react-dom-builtin: undefined () react-dom-experimental-builtin: undefined () react-draft-wysiwyg: ^1.15.0 => 1.15.0 react-error-boundary: ^4.0.11 => 4.0.11 react-experimental-builtin: undefined () react-hook-form: ^7.49.2 => 7.49.2 react-hot-toast: ^2.4.1 => 2.4.1 react-i18next: ^13.5.0 => 13.5.0 react-is: 18.2.0 react-map-gl: ^7.1.6 => 7.1.6 react-perfect-scrollbar: ^1.5.8 => 1.5.8 react-popper: ^2.3.0 => 2.3.0 react-qr-code: ^2.0.12 => 2.0.12 react-redux: ^9.0.4 => 9.0.4 react-refresh: 0.12.0 react-server-dom-turbopack-builtin: undefined () react-server-dom-turbopack-experimental-builtin: undefined () react-server-dom-webpack-builtin: undefined () react-server-dom-webpack-experimental-builtin: undefined () react-use: ^17.4.0 => 17.4.2 regenerator-runtime: 0.13.4 rollbar: ^2.26.2 => 2.26.2 rollbar-sourcemap-webpack-plugin: ^3.3.0 => 3.3.0 sass-loader: undefined () scheduler-builtin: undefined () scheduler-experimental-builtin: undefined () schema-utils: undefined () semver: undefined () send: undefined () server-only: 0.0.1 setimmediate: undefined () shell-quote: undefined () source-map: undefined () stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () stylis: ^4.3.0 => 4.3.0 (4.2.0) stylis-plugin-rtl: ^2.1.1 => 2.1.1 superstruct: undefined () tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () ts-node: ^10.9.2 => 10.9.2 tty-browserify: undefined () typescript: ^5.2.2 => 5.2.2 ua-parser-js: undefined () unistore: undefined () util: undefined () vite-tsconfig-paths: ^4.2.1 => 4.2.1 vitest: ^1.1.0 => 1.1.0 vm-browserify: undefined () watchpack: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () ws: undefined () yup: ^1.3.2 => 1.3.2 zod: undefined () npmGlobalPackages: corepack: 0.22.0 npm: 10.2.3 ```

Describe the bug

I have the following code in my TypeScript React application, and I can confirm that it is being executed at runtime:

import { I18n } from 'aws-amplify/utils'

I18n.putVocabularies({
  en: { 'Confirm TOTP Code': 'Authentication Code' }
})

However, the ConfirmSignIn view continued to show the "Confirm TOTP Code" text instead:

image

This is in contrast to the same application using aws-amplify v5, which properly rendered the translation. I believe that the discrepancy is due to the way default language detection works between v5 and v6. The v6 Internationalization docs (as well as the v5 docs) claim that

In the browser, Amplify detects browser language automatically.

After adding a breakpoint in the ConfirmSignIn component and descending several frames (through getChallengeText and into the static I18n and the package-private I18n class) I found that the translation was failing because the wrapped I18n class's _lang property was null:

image

I was subsequently surprised to find that the I18n.setDefaultLanguage method--the code which is responsible for setting the _lang property using window.navigator.language--was not being called. Furthermore, because the wrapped I18n class is package-private, that method is not exposed for me to call.

Now, I can remedy this by cloning the contents of setDefaultLanguage in my codebase (in my case calling setLanguage('en') will likely be sufficient). But this appears to be a bug and not something that users should have to do. In v5 this is not an issue because the setDefaultLanguage method does not exist; its contents are simply included in the I18n class constructor.

The issue appears to have been introduced recently, when I18n was un-deprecated following its(temporary) deprecation:

Expected behavior

The language should be automatically detected, as advertised in the documentation.

Reproduction steps

  1. Install aws-amplify and @aws-amplify/ui-react (the latter package is not relevant to this bug report, only for the reproduction)
  2. Render the Authenticator using your favorite UI library (example in React, taken from the Authenticator component docs). Include a translation:

    import React from 'react';
    import { Amplify } from 'aws-amplify';
    import { I18n } from 'aws-amplify/utils'
    
    import { Authenticator, translations } from '@aws-amplify/ui-react';
    import '@aws-amplify/ui-react/styles.css';
    
    import awsExports from './aws-exports';
    Amplify.configure(awsExports);
    
    // Note that this demo assumes the browser's default language is English.
    // If yours is something different, edit the `en` prefix.
    I18n.putVocabularies(translations)
    I18n.putVocabularies({
     en: { Email: 'Hello World!' }
    })
    
    export default function App() {
     return (
       <Authenticator>
         {({ signOut, user }) => (
           <main>
             <h1>Hello {user.username}</h1>
             <button onClick={signOut}>Sign out</button>
           </main>
         )}
       </Authenticator>
     );
    }
  3. Start up the application and navigate to the landing page
  4. The email input will not say "Hello World!". It will say "Email".

Code Snippet

See above.

Log output

No informative logs to report

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

cwomack commented 8 months ago

@milotoor, thank you for opening this issue. I'm going to mark this as a bug and review this with the team internally. We'll keep you posted on when we have a fix ready!

jimblanc commented 8 months ago

@milotoor Good day, a fix for this issue made it out with Amplify 6.0.10. Could you please let us know if this release resolved your issue?

milotoor commented 8 months ago

@jimblanc thank you for letting me know! I can confirm that v6.0.10 addresses my issue. I appreciate the swift turnaround!