Giter VIP home page Giter VIP logo

i18n's People

Contributors

arnthors avatar dependabot[bot] avatar fnando avatar goooice avatar honzasterba avatar joshuayoes avatar kiskoza avatar michalkos avatar rpellerin avatar thewirv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

i18n's Issues

Feature Request: ignore '.' (dot) in translation keys

I was having same issue as people in i18n-js issues like this one:
fnando/i18n-js#424

Maybe somebody will need solution for i18n library:

  1. import library from ./src like that:
    import { I18n, TranslateOptions } from 'i18n-js/src';

  2. add defaultSeparator
    const i18n: I18n = new I18n(translations, { defaultSeparator: '|' });

  3. apply patch-package (https://github.com/ds300/patch-package)
    here is it's code:

diff --git a/node_modules/i18n-js/src/I18n.ts b/node_modules/i18n-js/src/I18n.ts
index 43476f5..d53712e 100644
--- a/node_modules/i18n-js/src/I18n.ts
+++ b/node_modules/i18n-js/src/I18n.ts
@@ -255,11 +255,11 @@ export class I18n {
    * @returns {void}
    */
   public store(translations: Dict): void {
-    const map = propertyFlatList(translations);
+    const map = propertyFlatList(translations, this.defaultSeparator);
 
-    map.forEach((path) =>
-      set(this.translations, path, get(translations, path)),
-    );
+    map.forEach((path) => {
+      this.translations[path] = translations[path.split(this.defaultSeparator)[0]][path.split(this.defaultSeparator)[1]]
+    })
 
     this.hasChanged();
   }
diff --git a/node_modules/i18n-js/src/helpers/lookup.ts b/node_modules/i18n-js/src/helpers/lookup.ts
index 595d17c..b11dd27 100644
--- a/node_modules/i18n-js/src/helpers/lookup.ts
+++ b/node_modules/i18n-js/src/helpers/lookup.ts
@@ -36,9 +36,7 @@ export function lookup(i18n: I18n, scope: Scope, options: Dict = {}): any {
     .map((component) => i18n.transformKey(component))
     .join(".");
 
-  const entries = locales.map((locale) =>
-    get(i18n.translations, [locale, scope].join(".")),
-  );
+  const entries = locales.map((locale) => i18n.translations[[locale, scope].join(i18n.defaultSeparator)]);
 
   entries.push(options.defaultValue);
 
diff --git a/node_modules/i18n-js/src/helpers/propertyFlatList.ts b/node_modules/i18n-js/src/helpers/propertyFlatList.ts
index 5ebc9e2..d83ee90 100644
--- a/node_modules/i18n-js/src/helpers/propertyFlatList.ts
+++ b/node_modules/i18n-js/src/helpers/propertyFlatList.ts
@@ -10,9 +10,11 @@ interface Indexable {
 
 class PropertyFlatList {
   public target: Dict;
+  public defaultSeparator: string;
 
-  constructor(target: Dict) {
+  constructor(target: Dict, defaultSeparator: string) {
     this.target = target;
+    this.defaultSeparator = defaultSeparator;
   }
 
   call(): string[] {
@@ -30,8 +32,7 @@ class PropertyFlatList {
   compute(value: unknown, path: string): unknown {
     if (!isArray(value) && isObject(value)) {
       return Object.keys(value).map((key) => 
-        this.compute((value as Indexable)[key] as unknown, `${path}.${key}`),
-      );
+        this.compute((value as Indexable)[key] as unknown, `${path}${this.defaultSeparator}${key}`));
     } else {
       return path;
     }
@@ -70,6 +71,6 @@ class PropertyFlatList {
  *
  * @returns {string[]} The list of paths.
  */
-export function propertyFlatList(target: Dict): string[] {
-  return new PropertyFlatList(target).call();
+export function propertyFlatList(target: Dict, defaultSeparator: string): string[] {
+  return new PropertyFlatList(target, defaultSeparator).call();
 }

Feature Request: Add function to return locale that's currently used by the library

Description

Let's say your app supports english and german language. User with czech locale logs in and the app fallbacks to english.

Currently, if you setup i18n like this:

export const i18n = new I18n(
  enableHiddenFeatures
    ? translations
    : {
        en:  translations.en,
        de: translations.de,
      }
)
i18n.locale = 'cs'
i18n.defaultLocale = 'en'
i18n.enableFallback = true

i18n.locale returns "cs" despite en translations being used.

Describe the solution

Add function getUsedLocale() that will return locale that is currently used by the library.

Alternatives you considered

In my example above, we can test keys(translations).include(I18n.locale), but parsing language code is not that straight forward usually it might be in format like da_DK or de_DE. This logic is already included in the library and it does not seem right to duplicate it to find out what language is used.

Feature Request: Typing for loaded translations, instead of "string | string[]"

Description

Today the i18n object methods that accepts "Scope" as an argument are simply: type Scope = string | string[]

Describe the solution

My solution is making the i18n class generic and the Scope type will be depending on the translations object loaded to i18n.

Alternatives you considered

I have considered making a redeclare in my project, the better solution will be making i18n generic and it will improve the developer experience.

Additional context

I already made the changes locally and waiting for a permission to make a PR.

Bug: i18.t(key) key use like cardno or phoneno can not been properly found.

Description

very similar key exist may return object but not string translation.

How to reproduce

For Example I have below two key with translation
image

I get translation result below
image

What do you expect

properly render result with similar key like cardno cardno. or phoneno phoneno.

What happened instead

return{"": undefined, "0": "P", "1": "h", "2": "o", "3": "n", "4": "e", "5": " ", "6": "#"}

Software:

using "i18n-js": "4.3.2"

Feature Request: reconsider vendoring lodash

Description

Hi, the newly released v4.3.0 vendored the whole lodash library to improve compatibility with importmap

However, this choice comes with some drawbacks, like:

  • File size increased by more than 500%, from 1.4MB to 7.53MB
  • Inability to reuse code from lodash, if other libraries are using the same lodash functionalities
  • Update concerns: the gem will require a release after each lodash release
  • Security concerns: if a new CVE will be found in lodash affecting one of the functionalities used in i18n-js, this library will potentially be exposed to CVEs
  • Issues with third-parties: #66

Describe the solution

I do not know a solution, I'm going to make some proposals:

  • Vendor just the minimum amount of code possible
  • Remove unnecessary lodash dependencies, like the deprecated isArray (probably a breaking change that require a major release)
  • Check if this is an issue with importmap not being able to resolve lodash, or with lodash itself. This is probably related to lodash/lodash#4366 (comment)

Alternatives you considered

  • Fork
  • Lock to 4.2.3

Additional context

I'm not a JavaScript developer, but I'm willing to help in finding an alternative

i18n.numberToPercentage(undefined) throws an error

Description

i18n.numberToPercentage(undefined)

Throws an error:

TypeError: Cannot read properties of undefined (reading 'toString') (webpack-internal:///./node_modules/i18n-js/dist/import/helpers/formatNumber.js:60)

The original code is here https://github.com/fnando/i18n/blob/main/src/helpers/formatNumber.ts#L89

  if (originalNumber.isNaN()) {
    formattedNumber = input.toString();
  }

What do you expect

The function will return undefined if the input is undefined

Software:

"i18n-js": "4.0.0-alpha.14"

Regression: not able to interpolate over an array

Description

I recently upgraded from v3.8 to v.4.1.1 but it seems that in this version we're not able to interpolate over an array, which was possible using v3.8, so I thinks it's a regression.

How to reproduce

Just add to your translations a simple array like:

someTranslation: ["Some text", "Value of something is {{value}}"]

Then try to interpolate over it, like:

i18n.t('someTranslation', { value: 123 })

What do you expect

It should give the following result: ["Some text", "Value of something is 123"]

What happened instead

It doesn't throw any error, just returns: ["Some text", "Value of something is {{value}}"]

Bug: Error importing flattenDeep module from Lodash using importmap

When using the library with importmap the following error is thrown:

The requested module 'lodash' does not provide an export named 'flattenDeep'

The offending code appears to be at the very top of /dist/import/index.js, in the first import statement:

import{uniq as e,camelCase as n,repeat as r,get as i,zipObject as s,sortBy as o,flattenDeep as a,isArray as l,isObject as c,range as u,set as h,has as d}from"lodash";

I'm able to reproduce the error in JSPM's sandbox using the following code:

<script type="importmap">
{
  "imports": {
    "i18n-js": "https://ga.jspm.io/npm:[email protected]/dist/import/index.js"
  },
  "scopes": {
    "https://ga.jspm.io/": {
      "bignumber.js": "https://ga.jspm.io/npm:[email protected]/bignumber.mjs",
      "lodash": "https://ga.jspm.io/npm:[email protected]/lodash.js"
    }
  }
}
</script>
<script type="module">
  import { i18nJs } from "i18n-js";
  console.log(i18nJs);
</script>

I don't see anything wrong with the import statement, but then again exports/imports aren't really in my wheelhouse. Could the problem instead be with the way Lodash exports flattenDeep?

Thanks!

Error: While trying to resolve module `make-plural`

Description

I have a React Native project that using i18n-js. But when I execute the building, I have the following error:

Error: While trying to resolve module make-pluralfrom file/node_modules/i18n-js/dist/import/Pluralization.js, the package /node_modules/make-plural/package.jsonwas successfully found. However, this package itself specifies amain module field that could not be resolved (/node_modules/make-plural/plurals.mjs. Indeed, none of these files exist:

"React native": "0.67.5"
"i18n-js": "^4.2.3"

Bug: Cannot read property 'get' of undefined

Description

When I tried to load some translations with i18n-js, I have an error like this one :

CleanShot 2023-10-21 at 08 16 55@2x

How to reproduce

My repository is a Solito monorepo and I want to use your library to translate the React Native part.

To reproduce this error :

What do you expect

[Describe what do you expect to happen]

I would like there to be no more errors when calling the get method

Full backtrace

TypeError: Cannot read property 'get' of undefined

This error is located at:
    in Header (created by HomeScreen)
    in RCTView (created by View)
    in View
    in NativeWind.View
    in NativeWind.NoName
    in Unknown (created by HomeScreen)
    in HomeScreen (created by Home)
    in Home
    in Unknown (created by Route(index))
    in Route (created by Route(index))
    in Route(index) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen
    in Unknown (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaInsetsContext)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator
    in Unknown (created by Root)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by Provider)
    in Provider (created by Root)
    in Root
    in Unknown (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in RCTView (created by View)
    in View (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by wrapper)
    in wrapper (created by ContextNavigator)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by withDevTools(App))
    in withDevTools(App) (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes

Bug: Missing src for source map generation in CRA

Description

When using i18n-js with Create React App, webpack is not able to find src folder and cannot generate source map and I got warning in compilation.

How to reproduce

  1. Create a project with Create React App
  2. Install the package
  3. Import and use the package: simply create a new i18n class:
import { I18n } from 'i18n-js'

const i18n = new I18n()

What do you expect

No warning should be appear in console

What happened instead

Warning about missing file is generated

Software:

  • React version: 18.2.0
  • React scripts version: 5.0.1
  • 18n-js version: 4.2.2

Full backtrace

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\I18n.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\I18n.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\Locales.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\Locales.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\MissingTranslation.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\MissingTranslation.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\Pluralization.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\Pluralization.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\camelCaseKeys.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\camelCaseKeys.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\createTranslationOptions.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\createTranslationOptions.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\expandRoundMode.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\expandRoundMode.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\formatNumber.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\formatNumber.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\getFullScope.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\getFullScope.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\index.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\index.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\inferType.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\inferType.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\interpolate.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\interpolate.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\isSet.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\isSet.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\lookup.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\lookup.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToDelimited.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToDelimited.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToHuman.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToHuman.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToHumanSize.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\numberToHumanSize.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\parseDate.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\parseDate.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\pluralize.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\pluralize.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\propertyFlatList.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\propertyFlatList.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\roundNumber.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\roundNumber.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\strftime.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\strftime.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\timeAgoInWords.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\helpers\timeAgoInWords.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\index.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\index.ts'

Failed to parse source map from 'C:\Users\path-to-project\node_modules\i18n-js\src\typing.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\path-to-project\node_modules\i18n-js\src\typing.ts'

Require cycle warning

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch [email protected] for the project I'm working on.

I was trying to find a solution for the annoying warning I get everytime I run my React Native app:

**WARN**  Require cycle: node_modules\i18n-js\dist\import\helpers\index.js -> node_modules\i18n-js\dist\import\helpers\formatNumber.js -> node_modules\i18n-js\dist\import\helpers\index.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoalues. Consider refactoring to remove alues. Consider refactoring to remove the need for a cycle. 

Here is the diff that solved my problem:

diff --git a/node_modules/i18n-js/dist/import/helpers/formatNumber.js b/node_modules/i18n-js/dist/import/helpers/formatNumber.js
index 5c39971..8856136 100644
--- a/node_modules/i18n-js/dist/import/helpers/formatNumber.js
+++ b/node_modules/i18n-js/dist/import/helpers/formatNumber.js
@@ -1,6 +1,7 @@
 import BigNumber from "bignumber.js";
 import { repeat } from "lodash";
-import { roundNumber } from ".";
+import { roundNumber } from "./roundNumber";
+
 function replaceInFormat(format, { formattedNumber, unit }) {
     return format.replace("%n", formattedNumber).replace("%u", unit);
 }

This issue body was partially generated by patch-package.

Why dependencies on bignumber.js and lodash

Hi,

I simply want to perform translations without use of above two libraries. When I add this library using importmap on Rails 7 application, it also adds bignumber and lodash in my assets.

I still get error even when I added these two files in my assets.
I get error as "The requested module 'lodash' does not provide an export named 'flattenDeep'".

Is there any specific reason that these two libraries are automatically added when we add i18n library?

Can you help me out how I can get it fixed?

Thanks.

Official way to use require folder instead of import

I'm currently looking for a way to use this package using React & Next.js but I get the following error Unexpected token 'export' due to the fact I can only use commonjs package.

Regarding the structure of the project I can see 3 folders under the dist folder : import, browser & require. The main file registered in package.json is dist/import/index.js.

So I found 2 way to fix this:

  • Import i18n-js/dist/require but in Typescript I get the following error Could not find a declaration file for module i18n-js
  • Create a fork of the project that only change the main file to dist/require/index.js

So I go into the second solution, for those facing the same issues you can find the package here: https://www.npmjs.com/package/@lagregance/i18n-js-require

Maybe I miss it, but since the relevant package is available inside the dist folder we should have a way to use it without making a fork (my idea is to publish alternative version like 4.2.2_require).

Thanks for help.

i18n fails when used via Importmaps

Description

I have attempted to install, configure and use i18n-js via Importmaps (via Rails). Unfortunately, I get a ton of failing GET requests, where Lodash appears to look for the .js files using wrong paths.

How to reproduce

The installation:

$ ./bin/importmap pin [email protected] --download

The resulting config/importmap.rb

pin "i18n-js" # @4.2.3
pin "bignumber.js" # @9.1.1
pin "lodash/camelCase", to: "lodash--camelCase.js" # @4.17.21
pin "lodash/flattenDeep", to: "lodash--flattenDeep.js" # @4.17.21
pin "lodash/get", to: "lodash--get.js" # @4.17.21
pin "lodash/has", to: "lodash--has.js" # @4.17.21
pin "lodash/isArray", to: "lodash--isArray.js" # @4.17.21
pin "lodash/isObject", to: "lodash--isObject.js" # @4.17.21
pin "lodash/range", to: "lodash--range.js" # @4.17.21
pin "lodash/repeat", to: "lodash--repeat.js" # @4.17.21
pin "lodash/set", to: "lodash--set.js" # @4.17.21
pin "lodash/sortBy", to: "lodash--sortBy.js" # @4.17.21
pin "lodash/uniq", to: "lodash--uniq.js" # @4.17.21
pin "lodash/zipObject", to: "lodash--zipObject.js" # @4.17.21
pin "make-plural" # @7.0.0

All corresponding .js files are downloaded to:

my_app/vendor/javascript/bignumber.js.js
my_app/vendor/javascript/i18n-js.js
my_app/vendor/javascript/lodash--camelCase.js
my_app/vendor/javascript/lodash--flattenDeep.js
my_app/vendor/javascript/lodash--get.js
my_app/vendor/javascript/lodash--has.js
my_app/vendor/javascript/lodash--isArray.js
my_app/vendor/javascript/lodash--isObject.js
my_app/vendor/javascript/lodash--range.js
my_app/vendor/javascript/lodash--repeat.js
my_app/vendor/javascript/lodash--set.js
my_app/vendor/javascript/lodash--sortBy.js
my_app/vendor/javascript/lodash--uniq.js
my_app/vendor/javascript/lodash--zipObject.js
my_app/vendor/javascript/make-plural.js

The resulting importmap script looks like this:

<script type="importmap" data-turbo-track="reload">{
    "imports": {
        ...
        "i18n-js": "/assets/i18n-js-04b620e607b4a8fc4d369deb77ddaca4c314ff3f5b113425aa02a5463c0f2a03.js",
        "bignumber.js": "/assets/bignumber.js-da37e3c473288a78d1c8f160c092a279052ebe856db1dcafe6e3d6d1b5afa239.js",
        "lodash/camelCase": "/assets/lodash--camelCase-6f67652d0026ec4ab6b1f27196f08a44304fa605aa6ff96fe6ec82fa285694d1.js",
        "lodash/flattenDeep": "/assets/lodash--flattenDeep-2f4edb1bfdbc4fbfdb2e7eefd3d37d5e2e4b88dee8f10c06789ddbb360057939.js",
        "lodash/get": "/assets/lodash--get-35a2d1636af7ea4edad2fda72147bffaa45bae5656450a0e43f0243ffddf7d6f.js",
        "lodash/has": "/assets/lodash--has-64e2b530099782a9245954fc3d0686a0435d5a4e36731b4487e53afa61487b41.js",
        "lodash/isArray": "/assets/lodash--isArray-90fbbd88ee79467a159561db8b16654aff7a93cedcdc52b7db2e16b0ae7afe87.js",
        "lodash/isObject": "/assets/lodash--isObject-4fab301185da7b0352cb57ea604e3424e95ab46992c48137bbcfe8e7251da840.js",
        "lodash/range": "/assets/lodash--range-c1e03f0ecbfd42e639fbd6729f8bc0b1ecef043c35ded308fcf0f9ae4360cb05.js",
        "lodash/repeat": "/assets/lodash--repeat-5664123cae867b181825acae4eb06f468f07dc03e88e20baceddf91b1696282b.js",
        "lodash/set": "/assets/lodash--set-82bc400373c55188224ac34f828c43950c4c575acca0d105024d85afe8b0f4e1.js",
        "lodash/sortBy": "/assets/lodash--sortBy-b081313fe9cbc9c19866f545b40357fc4a58f822fab6b893a1603c5c7b757fd6.js",
        "lodash/uniq": "/assets/lodash--uniq-b0fd5fd63d0fc1141fe47e7b2f16beefc916c1d87b07b43e69ee4813c105dac9.js",
        "lodash/zipObject": "/assets/lodash--zipObject-db9bbd8ec0b6e7ebc0cde82b511a40ff8fb16457fe92b7532903f07b172c2db4.js",
        "make-plural": "/assets/make-plural-2d052f6889f01180b0da040eb353fe7f921e763196a1003a289337fa09a8f10d.js",
        ...
    }
}</script>

The import statement in: my_app/javascript/controllers/my_controller.js

import { I18n } from "i18n-js";
console.log(I18n);

Some of the resulting failing requests, upon page load:

GET http://127.0.0.1:3000/assets/isArray.js
GET http://127.0.0.1:3000/assets/_/51cf0f3b.js
GET http://127.0.0.1:3000/assets/_/301ffe46.js
GET http://127.0.0.1:3000/assets/isObjectLike.js
GET http://127.0.0.1:3000/assets/isSymbol.js
GET http://127.0.0.1:3000/assets/_/bc38db9b.js
GET http://127.0.0.1:3000/assets/isObject.js
GET http://127.0.0.1:3000/assets/isFunction.js
GET http://127.0.0.1:3000/assets/_/e44fb5c7.js
GET http://127.0.0.1:3000/assets/_/27ce0419.js
GET http://127.0.0.1:3000/assets/_/da7e18fe.js
GET http://127.0.0.1:3000/assets/eq.js
GET http://127.0.0.1:3000/assets/_/6d2b6c8f.js
GET http://127.0.0.1:3000/assets/memoize.js
GET http://127.0.0.1:3000/assets/_stringToPath.js
GET http://127.0.0.1:3000/assets/_arrayMap.js
GET http://127.0.0.1:3000/assets/_/5bbd3627.js
GET http://127.0.0.1:3000/assets/toString.js
GET http://127.0.0.1:3000/assets/_toKey.js
GET http://127.0.0.1:3000/assets/isArguments.js
GET http://127.0.0.1:3000/assets/isLength.js
GET http://127.0.0.1:3000/assets/_/25787e84.js
GET http://127.0.0.1:3000/assets/_/db1f5abb.js

Let's take a look at the 1st failing request (line 1):

GET http://127.0.0.1:3000/assets/isArray.js

The request that has lead to this error shows: Lodash's _.has is the origin

http://127.0.0.1:3000/assets/lodash--has-64e2b530099782a9245954fc3d0686a0435d5a4e36731b4487e53afa61487b41.js

This .js file contains "problematic" import statements such as...

import"./isArray.js";

...as you can see in the full code:

import"./isArray.js";import"./_/51cf0f3b.js";import"./_/301ffe46.js";import"./isObjectLike.js";import"./isSymbol.js";import"./_/bc38db9b.js";import"./isObject.js";import"./isFunction.js";import"./_/e44fb5c7.js";import"./_/27ce0419.js";import"./_/da7e18fe.js";import"./eq.js";import"./_/6d2b6c8f.js";import"./memoize.js";import"./_stringToPath.js";import"./_arrayMap.js";import"./_/5bbd3627.js";import"./toString.js";import"./_toKey.js";import"./isArguments.js";import"./isLength.js";import"./_/25787e84.js";import{_ as r}from"./_/db1f5abb.js";var t={};var s=Object.prototype;var i=s.hasOwnProperty;
//...

Software:

  • Package version: v4.2.3
  • Ruby version: ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]

Bug: Unable to use with jest

Description

How to reproduce

 import { Dict, I18n, I18nOptions, Scope, TranslateOptions } from "i18n-js";

What do you expect

No error

What happened instead

  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    C:\p\spring-docker\node_modules\i18n-js\dist\import\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { I18n } from "./I18n";
                                                                                             ^^^^^^

    SyntaxError: Unexpected token 'export'

Software:

  • Jest with "preset": "jest-expo",
  • Gem version: [Add gem version here]
  • Ruby version: [Add version here]

Full backtrace

[Paste full backtrace here]

Feature Request: To allow passing `missingBehavior` as option to `translate`

Description

At this point, the missingBehavior is one of the i18n options that is set at the class instance creation

this.missingBehavior = missingBehavior;

Having a few strategies of how to deal with a missing translation is great, but a lot of times we UI would benefit from a dynamic choice of what behavior to use for a particular UI place.

For example, if I have a enumerable set of translations for some predefined types: "cat", "dog", "rat".

en:
  animals:
    cat: Cat
    dog: Dog
    rat: Rat

and I have a UI

const getAnimalLabel = (type) =>
  <span class="my-animal">{i18n.t(`animals.{type}`)}</span>

I want this function to return an empty span if there is no translation. I don't want an error or a string like <span>"[missing "animals.bird" translation]"</span> for this particular UI place. Currently, there is no easy way to deal with this simple case.

Describe the solution

There is a small solution that unlocks this scenario, just updating a single line

return this.registry[this.i18n.missingBehavior](this.i18n, scope, options);

into

  public get(scope: Scope, options: Dict): string {
    return this.registry[options.missingBehavior || this.i18n.missingBehavior](this.i18n, scope, options);
  }

in this case, I could register my custom strategy:

const emptyStrategy = () => undefined

class PatchedMissingTranslation extends MissingTranslation {
  constructor(...args) {
    super(...args)
    this.register('empty', emptyStrategy)
  }
}

And use it in my code:

const getAnimalLabel = (type) =>
  <span class="my-animal">{i18n.t(`animals.{type}`, {missingBehavior: 'empty'})}</span>

Alternatives you considered

The alternative is to override the get method in the user code. This works but maybe a problem in the long run if the i18n would change the MissingTranslation implementation

Additional context

Also, it would be great to include a suggested empty strategy into the list of default strategies

this.register("guess", guessStrategy);
this.register("message", messageStrategy);
this.register("error", errorStrategy);

Bug: after upgrade to 4.x, i got a lot of Typescript Errors

After upgrading to the latest version, i got a lot of typescript errors.

TS2551: Property 'locale' does not exist on type 'typeof import("/node_modules/i18n-js/typings/index")'. Did you mean 'Locales'?
TS2339: Property 't' does not exist on type 'typeof import("/node_modules/i18n-js/typings/index")'.

I've tried to remove @types/i18n-js, but nothing has changed.

Bug: i18n.t return type shouldn't be only string

Description

i18n allows us to return a translation for a scope as an array or an object, but i18n.t has only string as return type, causing TypeErrors if you try to use it as something that isn't a string.

How to reproduce

Just try to use a directly return from i18n.t as string[] or some object type.

What do you expect

i18n.t should have more than just string as return type.

What happened instead

TypeError, because i18n.t always return a string, according to its type.

Bug: I18n is not a constructor

Description

After updating the package all versions after 4.4.0. I'm getting error when I tryied to load the package with configurations.

What do you expect

To run without errors.

What happened instead

It getting error.

Software:

i18n version > 4.4.0

Full backtrace

2024-02-14_16h16_22

Error importing module with WebPack since version 4.4.0

Description

When upgrading I18n-js to 4.4.0+ we have an error : I18n is not a constructor

How to reproduce

You can reproduce with following sandbox, downgrading to 3.2.0 will make the page work.
https://codesandbox.io/p/sandbox/upbeat-lamarr-hpz9qp?file=%2Fpackage.json%3A14%2C31

What do you expect

Page should load without error.
image

What happened instead

image

Software:

  • Gem version: [Add gem version here]
  • Ruby version: [Add version here]

Full backtrace

renderWithHooks
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:16305:18
mountIndeterminateComponent
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:20074:13
beginWork
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:21587:16
HTMLUnknownElement.callCallback
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:4164:14
Object.invokeGuardedCallbackDev
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:4213:16
invokeGuardedCallback
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:4277:31
beginWork$1
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:27451:7
performUnitOfWork
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:26557:12
workLoopSync
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:26466:5
renderRootSync
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:26434:7
performConcurrentWorkOnRoot
https://hpz9qp.csb.app/node_modules/react-dom/cjs/react-dom.development.js:25738:74
workLoop
https://hpz9qp.csb.app/node_modules/scheduler/cjs/scheduler.development.js:266:34
flushWork
https://hpz9qp.csb.app/node_modules/scheduler/cjs/scheduler.development.js:239:14
MessagePort.performWorkUntilDeadline
https://hpz9qp.csb.app/node_modules/scheduler/cjs/scheduler.development.js:533:21

Missing Export In Browser Index.js

Description

Missing export in browser/index.js

How to reproduce

import { I18n } from 'i18n-js';

What do you expect

Import the I18n.

What happened instead

It's returning void.

Software:

  • Gem version: 4.2.3
  • Ruby version: 3.2.3

Full backtrace

18:54:16 js.1       | ▲ [WARNING] Import "I18n" will always be undefined because the file "../../node_modules/i18n-js/dist/browser/index.js" has no exports [import-is-undefined]
18:54:16 js.1       | 
18:54:16 js.1       |     modules/i18n.js:1:9:
18:54:16 js.1       |       1 │ import { I18n } from 'i18n-js';

Bug: It's not possible to use `formatNumber` without `options`

As in the title, it is not possible to omit options argument of formatNumber.
There is an example in the readme indicating it should work:

i18n.t("points", {
  count: points,
  points: i18n.formatNumber(points),
});

However, this actually leads to following error:

formatNumber.js:17 Uncaught TypeError: Cannot read properties of undefined (reading 'raise')
    at formatNumber (formatNumber.js:17:1)
    at I18n.formatNumber (I18n.js:274:28)

Passing empty object as options results in NaN being returned.

What do you expect

As in the example, and similar to how to Intl allows, I would expect that it's possible to omit the options param:

Intl.NumberFormat().format(14.45435)

Software:

  • NPM package: v4.3.2

Interpolate with component

Hi,

you mention to build a custom interpolate function, do you have any example on how it would look like to do this:

const i18n = new I18n({
  en: { greetings: "Hi, %{name}!" },
  "pt-BR": { greetings: "Olá, %{name}!" },
});

i18n.interpolate = (i18n, message, options) => {
  // ...
};

return <Text>{i18n.t("greetings", { name: <BoldText>John</BoldText> })}</Text>;

Thanks

Bug: translate method can return a JS Object in some cases, where a String is always expected

Description

If i18n.translate(scope) does not target a leaf node the return is an object. This generally is useless in the UI, in this case, it would be better to return a standard missing translation string.

How to reproduce

const i18n = new I18n({en: {labels: {a: "A"}}})
console.log(i18n.translate('labels'))

Output:

[object Object]

What do you expect

Ideally, it should be claimed as missing translation and processed via a missing translation strategy. So for a default case of using message strategy, it would be expected to get a string:

[missing "en.labels" translation]

What happened instead

An object was returned, despite the original intent of always returning a string from translate method. As per the source code

return translation as string;

Software:

"i18n-js": "4.0.0-alpha.14"

Typescript: 'I18n' can only be imported by using a default import

Description

Importing asimport { I18n } from 'i18n-js'; throws TS error 'I18n' can only be imported by using a default import . Importing as default import import I18n from 'i18n-js'; throws on new I18n()
This expression is not constructable. Type 'typeof I18n' has no construct signatures.

How to reproduce

Use I18n as described in docs

What do you expect

Not to throws Typescript error

Software:

  • Ruby version: 2.7.6
  • React Native: 0.73.4
  • I18n: 4.4.0

Bug: Documentation doesn't match implementation or types

Description

[https://github.com/fnando/i18n/tree/main#missing-translations] lists several ways to register fallback languages but that doesn't work.

// Using an array
i18n.locales.register("no", ["nb", "en"]);

// Using a string
i18n.locales.no.register("nb");

// Using a function.
i18n.locales.no.register((locale) => ["nb"]);

Only the first variant works, i18n.locales.${localename}.register doesn't work.

Also when I tried to use the first variant i18n.locales.register("de", ["en"]); to set "en" as fallback for "de", then it failed with i18n.t("existingkey") even though i18n.translations.de.existingkey existed and i18n.locale was set to de.

How to reproduce

I18n.locales.de.register("en");

What do you expect

Missing behavior to be registered

What happened instead

- error TypeError: Cannot read properties of undefined (reading 'register')

Software:

  • i18n-js version: 4.3.2

Bug: Package not working with Next.js

Description

Package seems to not work with Next.js anymore.

How to reproduce

npx create-next-app i18n-test --ts
npm i i18n-js@latest

Create data.json in root folder.

{
    "Hello" : "Guten morgen"
}

Create i18n.ts in root folder.

import { I18n } from "i18n-js";
import data from './data.json'

export const i18n = new I18n({
    ...data
})

Use translation in any page to reproduce the bug.

Software:

node: 16.13.2
next: 13.2.3
react: 18.2.0

Full backtrace

error - /Users/michal/Documents/projects/i18n-test/node_modules/i18n-js/dist/import/index.js:1
export { I18n } from "./I18n";
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.i18n-js (/Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:54:18)
    at __webpack_require__ (/Users/michal/Documents/projects/i18n-test/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///./i18n.ts:5:65)
    at Object../i18n.ts (/Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:32:1)
    at __webpack_require__ (/Users/michal/Documents/projects/i18n-test/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///./pages/index.tsx:9:63)
    at Object../pages/index.tsx (/Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:43:1)
    at __webpack_require__ (/Users/michal/Documents/projects/i18n-test/.next/server/webpack-runtime.js:33:42)
    at __webpack_exec__ (/Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:97:39)
    at /Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:98:28
    at Object.<anonymous> (/Users/michal/Documents/projects/i18n-test/.next/server/pages/index.js:101:3)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.requirePage (/Users/michal/Documents/projects/i18n-test/node_modules/next/dist/server/require.js:88:12)
    at /Users/michal/Documents/projects/i18n-test/node_modules/next/dist/server/load-components.js:49:73
    at async Object.loadComponentsImpl [as loadComponents] (/Users/michal/Documents/projects/i18n-test/node_modules/next/dist/server/load-components.js:49:26)
    at async DevServer.findPageComponentsImpl (/Users/michal/Documents/projects/i18n-test/node_modules/next/dist/server/next-server.js:599:36) {
  page: '/'
}

numberToPercentage behaves inconsistent to arguments

Description

If precision option is not passed to numberToPercentage it will return 'NaN%' regardless of input

How to reproduce

> I18n.numberToPercentage(55.55)

'NaN%'

> I18n.numberToPercentage(55.55, {precision: 0})

'56%'

What do you expect

I'd expect a default precision to kick in and return a numeric string value. The same applies to localize calls, now it is

> I18n.l("percentage", 123.45)

'NaN%'

Software:

"i18n-js": "4.0.0-alpha.14",

Chore: webpack (and probably esbuild) troubleshooting in the readme should not be needed anymore

Description

The instructions for using webpack with i18n at https://github.com/fnando/i18n?tab=readme-ov-file#im-using-webpack-and-bundling-doesnt-work are likely outdated and should be reviewed/removed.

These instructions were introduced due to issues with the exports field in version 4.4.1 of i18n. However, it seems these modifications caused further problems with webpack and esbuild. Additionally, changing the default resolve.conditionNames as advised might have unintended consequences for other libraries in large applications.

Feature Request: About Vendor Lodash

Description

I had a problem with the 4.3.0 that I wanted to share.
My Nuxt 3 production build failed because of relative dependencies added in the generated js.
It took me a while to realize it came from the i18n package.
The relatives path added in the nuxt generated js concerned your '/src/vendor/lodash' directory

Describe the solution

Anyway, browsing in your repo I see that these directory has been remove in 4.3.1-beta. So I upgrade and it's ok now.

Bug: Cannot read property 'prototype' of undefined error

Description

In a react-native expo iOS app, after upgrading i18n-js to version 4+ (tested with 4.4.3, 4.4.2, and 4.0.0), I get a "Cannot read property 'prototype' of undefined" error when I try to instantiate a new I18n class.

This error has been reported here but I could only fix it by downgrading to version 3.8.0

How to reproduce

Here's the code that triggers this issue:

import * as Localization from 'expo-localization';
import I18n from 'i18n-js';
import { en, fr, ru, ua, ca, de, it, sv, pl } from './languages';

const i18n = new I18n({ en, fr, ru, ua, ca, de, it, sv, pl });

i18n.fallbacks = true;
i18n.defaultLocale = 'en';
i18n.locale = Localization.locale;

export {i18n};

What do you expect

const i18n instantiated properly

What happened instead

"Cannot read property 'prototype' of undefined error"

Full backtrace

Here's a screenshot of the stacktrace:

24-05-15 11-05-01 7079

Bug: Crash with missing pluralization key

Description

My app's main language is English, but it needs to support a few others, e.g.: Arabic. Arabic does not have the same pluralization rules as English, so I had to add a custom code to use "zero", "one", "two", etc. Unfortunately there are some missing translations in the app, where I need to fall back to English. However, when the pluralization key is not present, it crashes instead of giving the usual error message.

How to reproduce

import { I18n } from "i18n-js";

const i18n = new I18n({
  "ar": {
    "weeks": {
      "one": "1 week ago",
      "other": "%{count} weeks ago"
    }
  }
});

i18n.pluralization.register('ar', (_i18n, count) => {
  // Based on https://github.com/ruby-i18n/i18n/blob/master/test/test_data/locales/plurals.rb
  if (count === 0) {
    return ['zero'];
  }
  if (count === 1) {
    return ['one'];
  }
  if (count === 2) {
    return ['two'];
  }
  if ([3, 4, 5, 6, 7, 8, 9, 10].includes(count % 100)) {
    return ['few'];
  }
  if (Number.isInteger(count)) {
    return ['many'];
  }

  return ['other'];
});

i18n.locale = 'ar';

console.log(i18n.t("not_existing", { count: 1 })); // -> [missing "ar.not_existing" translation]
console.log(i18n.t("weeks", { count: 1 })); // -> 1 week ago
console.log(i18n.t("weeks", { count: 2 })); // -> Uncaught TypeError: message is undefined

What do you expect

It would be nice to get the same fallback as I have for missing keys (e.g.: [missing "ar.weeks.two" translation] )

What happened instead

It raises an error and the whole page crashes.

Software:

Full backtrace

Uncaught TypeError: message is undefined
    interpolate ./node_modules/i18n-js/dist/import/helpers/interpolate.js:7
    pluralize ./node_modules/i18n-js/dist/import/helpers/pluralize.js:26
    pluralize ./node_modules/i18n-js/dist/import/I18n.js:118
    translate ./node_modules/i18n-js/dist/import/I18n.js:87
    <anonymous> ./src/index.js:43

Feature Request: auto load required plurizers

Description

If my understanding is correct, if you want to use different than default pluralizer you need to register when initializing i18n-js. This is different to rails-i18n where pluralizers are loaded based on locale.

Describe the solution

Implement similar mechanism where the locale files included in this lib would optionally refference pluralizer name used for given locale.

If this is in deed a good idea I will prepare a PR.

Bug: Unexpected token 'export'

Description

I have a pretty simple typescript project that runs on Docker. I tried to upgrade from 3.9.2 to 4.2.2, but have been running into issues building the project with the error Unexpected token 'export'. The error seems to be coming from the exports in the dist/index.js file.

Cannot `build` on current main

webpack has been removed from development dependencies, but it is still used in build:browser script

"build:browser": "webpack --output-path ./dist/browser/ --output-filename index.js --mode production --entry ./dist/import/index.js --output-library-type var --output-library-name I18n --devtool source-map",

Bug: JS v4.4.1 breaks with webpack, and changing `resolve.conditionNames` configuration is not expected

Incoming reproducible test case

https://github.com/diowa/icare/actions/runs/7872274448/job/21477141544?pr=1650#step:10:43

Relevant change: https://github.com/diowa/icare/pull/1650/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R32

Note

Sorry about the not-so-reduced test case. There are two JS errors, the second (google maps key) is unrelated. We are interested in the first one for this issue

Description

ERROR
i18n_js__WEBPACK_IMPORTED_MODULE_0__.I18n is not a constructor
TypeError: i18n_js__WEBPACK_IMPORTED_MODULE_0__.I18n is not a constructor

How to reproduce

import { I18n } from 'i18n-js'
import translations from 'src/locales/translations.json'

const i18n = new I18n(translations)

What do you expect

Since this is a minor release, I was expected the same behaviour as before. Or at least an entry in the changelog and updated documentation

What happened instead

Breaks JavaScript functionality

Software:

  • Gem version: 4.2.3
  • Ruby version: 3.3.0

Full backtrace

  1) Application protects pages from guest users
     Failure/Error: raise error_messages if severe_errors.any?
     
     RuntimeError:
       There were 2 JavaScript errors:
     
       http://127.0.0.1:54260/packs-test/js/application.js 217:13 Uncaught TypeError: i18n_js__WEBPACK_IMPORTED_MODULE_0__.I18n is not a constructor

Feature Request: Support delimited numbers for pluralization

Description

Numbers passed to pluralize via count are not delimited. For example, in en-US:

1234 results

…should be:

1,234 results

Describe the solution

A possible solution is to pass an optional displayCount string that overrides the numeric count in the output. For example:

const resultsCount = 1234;

i18n.t("results", {
  count: resultsCount,
  displayCount: i18n.numberToDelimited(resultsCount),
});

This would give more control over how the output is formatted. For example, if someone wanted to use numberToHuman instead of numberToDelimited.

Alternatives you considered

There’s no alternative to this as far as I can tell, given how count is parsed when a string is pluralized via zero, one, few, many, and other. Happy to be proven wrong. 🙂

Additional context

This is how pluralization works for FBT via PluralOptions.value.

Thanks for all your work on this library!

Bug: `toNumber` method disappeared in v4

Description

In v3 of this library there was a .toNumber method that appears to have been replaced by a formatNumber helper in v4, however, that helper is not exported. Is there a reason for not exporting it? Additionally, the old method is still being mentioned in one place in the README which is wrong.

How to reproduce

i18n.toNumber()

What do you expect

i18n.toNumber() does not throw an error, or is replaced by i18n.formatNumber which is publicly accessible and uses the formatNumber helper

What happened instead

i18n.toNumber() throws an error

Software:

  • Gem version: N/A
  • Ruby version: N/A

Full backtrace

TypeError: undefined is not a function

Can't import in Jest

Description

The I18n works but not in my Jest tests where it fails with the following error:

Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/igortsykalo/workspace/covalent-ojt/node_modules/i18n-js/dist/import/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { I18n } from "./I18n";
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'

    > 1 | import { I18n } from 'i18n-js';
        | ^
      2 | import en from './locales/en.json';
      3 | import es from './locales/es.json';
      4 |

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
      at Object.<anonymous> (app/javascript/i18n.js:1:1)

I've tried to follow Jest recommendations and added following to my jest.config.js:

  transform: {
    '^.+\\.(js|jsx)$': 'babel-jest',
  },
transformIgnorePatterns: ['<rootDir>/node_modules/(?!(i18n-js)/)'],

But this still did not help. I am using many other node_modules (react, material-ui, axios, etc.), but this is the first one that caused me issues.

How to reproduce

Use i18n-js with jest

What do you expect

works

What happened instead

fails

Software:

  • Gem version: v4
  • Ruby version: 2.7

Full backtrace

[Paste full backtrace here]

Bug: Incorrect translation when using numbers as keys

Description

We use i18n-js with translations for units and we request the translations of the entire set of units. This used to work in previous versions but after switching to version 4 this results in a incomplete array. When we remove '1' key the problem is solved.

Thank you for your great work on this package!

How to reproduce

import { I18n } from 'i18n-js'

export const i18n = new I18n()

i18n.store({ 'en': { 'units': { 'l': 'liter', '1': 'number' } } })
console.log(i18n.t('units'))
console.log(i18n.t('units.1'))
console.log(i18n.t('units.l'))

What do you expect

Expected this console output:

Object { l: "liter", 1: "number" }
number
liter

This is also what version 3.9.2 of i18n-js returned (using a similar setup).

What happened instead

This console output:

Array [ <1 empty slot>, "number" ]
number
liter

Software:

  • i18n-js gem version: 4.2.3
  • i18n-js npm version: 4.3.0
  • Ruby version: 3.1.3
  • Tested in firefox: 116.0.2

React Native i18n-js: Require cycles are allowed, but can result in uninitialized values

I have a React Native project that was using i18n-js.

This is the code:

import {I18n} from 'i18n-js';
import en from './en-US';
import pt from './pt-BR';

const translations = {en, 'pt-BR': pt};
type TranslationsTypes = keyof typeof translations;

const i18n = new I18n(translations);

export default i18n;

export const translate = (key: string) => i18n.t(key);

And this is a sample how I use:

import {translate} from 'i18n/src/locale';

<Text style={{color: '#DDDDDD', marginLeft: 5}}>
   {translate('text_1')}
</Text>

But when I start my React Native project, I get this warning:

Require cycle: node_modules/i18n-js/dist/import/helpers/index.js -> node_modules/i18n-js/dist/import/helpers/formatNumber.js -> node_modules/i18n-js/dist/import/helpers/index.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
Is this a i18n-js package problem, or did I something wrong?

Thanks

Refer to: https://stackoverflow.com/questions/73649189/react-native-i18n-js-require-cycles-are-allowed-but-can-result-in-uninitialize/74552208#74552208

Bug: Cannot convert object to primitive value

Description

Using the i18n-js library in a React Native Expo application along with Expo-Localization.

Translations JSON object includes 2 languages: English and Spanish. As of a few days ago, my i18n.t("key") function is returning "Cannot convert object to primitive value" error. This was not the case as of about a week ago so I suspect it might relate to a recent change.

One note - I am using the JSON object to organize my translations into sub-objects
UPDATE - this only occurs when translating the label of a React Native button. Will investigate further.

translations: {
    'en': {
        screen_1: {
            header: "Screen 1 header",
            text: "Screen 1 text"
        },
        screen_2: {
            header: "Screen 2 header",
            text: "Screen 2 text"
        }
    },
    'es': {
        screen_1: {
            header: "Encabezado de la pantalla 1",
            text: "Texto de la pantalla 1"
        },
        screen_2: {
            header: "Encabezado de la pantalla 2",
            text: "Texto de la pantalla 2"
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.