Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18next-scanner is removing every translation key with plural version #217

Closed
shaftwin opened this issue Sep 29, 2021 · 4 comments
Closed

Comments

@shaftwin
Copy link

shaftwin commented Sep 29, 2021

馃悰 Bug Report

Hello there,

I've been using i18next with i18next-scanner from a long time now. Everything was on track until today, where something really strange happened.
I'm working on a React-Native project. When I run yarn local:extract, every translation key with plural in it is removed from my translation files. If i rename count to anything else, it's parsed correctly. If I dare use count variable, the key is removed instantly from my translation files.

I did some research in this Github repository, in the doc and in StackOverflow, but i've seen nothing about a similar issue or any breaking changes.

I've just discovered this behavior recently, I tried to roll back to a previous version of my app when everything was working well but i found that, even on version where I've pushed plural key, if i run now local:extract, the script is deleting every plural key again...

I've tried to used in my config file. :

plural: function(lng, ns, key, options) {
    return true;
}

If I return false, I do get singular version of key, but if I return true, I don't get singular nor plural in my translation files.

I run out of solution and I'm asking for help

To Reproduce

Here is my config:

i18next-scanner.config.js

module.exports = {
  input: [
    './*.{js,jsx}',
    './components/**/*.{js,jsx}',
    './pages/**/*.{js,jsx}',
    './hooks/**/*.{js,jsx}',
    './services/**/*.{js,jsx}',
  ],
  output: './',
  options: {
    debug: false,
    removeUnusedKeys: true,
    sort: true,
    func: {
      list: ['i18next.t', 'i18n.t', 't'],
      extensions: ['.js', '.jsx'],
    },
    lngs: ['en', 'fr'],
    ns: ['common', 'validation', 'error', 'glossary', 'log'],
    defaultLng: 'en',
    defaultNs: 'common',
    defaultValue: '__STRING_NOT_TRANSLATED__',
    resource: {
      loadPath: './services/i18n/translations/{{lng}}/{{ns}}.json',
      savePath: './services/i18n/translations/{{lng}}/{{ns}}.json',
      jsonIndent: 2,
      lineEnding: '\n',
    },
    nsSeparator: ':',
    keySeparator: false,
    interpolation: {
      prefix: '{{',
      suffix: '}}',
    },
  },
};

initTranslation.js

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enCommon from './translations/en/common.json';
import frCommon from './translations/fr/common.json';
import enValidation from './translations/en/validation.json';
import frValidation from './translations/fr/validation.json';
import enError from './translations/en/error.json';
import frError from './translations/fr/error.json';
import enGlossary from './translations/en/glossary.json';
import frGlossary from './translations/fr/glossary.json';
import enLog from './translations/en/log.json';
import frLog from './translations/fr/log.json';

export const initTranslation = () => {
  return (
    i18n
      // detect user language
      // learn more: https://github.com/i18next/i18next-browser-languageDetector
      // pass the i18n instance to react-i18next.
      .use(initReactI18next)
      // init i18next
      // for all options read: https://www.i18next.com/overview/configuration-options
      .init({
        debug: true,
        fallbackLng: 'en',
        interpolation: {
          escapeValue: false, // not needed for react as it escapes by default
          // To avoid translating before init i18n and crash app. According to
          // offcial documentation: if your interpolation variables are user
          // provided or loaded from an external source, we strongly suggest
          // to set this option to true
          skipOnVariables: true,
        },
        resources: {
          en: {
            common: enCommon,
            validation: enValidation,
            error: enError,
            glossary: enGlossary,
            log: enLog,
          },
          fr: {
            common: frCommon,
            validation: frValidation,
            error: frError,
            glossary: frGlossary,
            log: frLog,
          },
        },
      })
  );
};

export default i18n;

package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "start-breaking": "BREAKING=yes expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject",
    "lint": "eslint --ext .js ./",
    "format": "yarn run format:prettier && yarn run lint --fix --quiet",
    "format:prettier": "prettier --write **/*.{json,yml}",
    "bump-patch": "yarn standard-version --release-as patch && git push && git push origin --tags",
    "bump-minor": "yarn standard-version --release-as minor && git push && git push origin --tags",
    "bump-major": "yarn standard-version --release-as major && git push && git push origin --tags",
    "build-dev-android": "rm -rf yarn.lock && rm -rf node_modules && yarn && expo build:android --release-channel `python3 ./services/releaseChannel/getIssueIdFromBranchName.py` --type apk",
    "build-formation-android": "rm -rf yarn.lock && rm -rf node_modules && yarn && expo build:android --release-channel formation --non-interactive",
    "build-prod-android": "rm -rf yarn.lock && rm -rf node_modules && yarn && expo build:android --release-channel prod-v$npm_package_version --non-interactive",
    "build-prod-android-breaking": "rm -rf yarn.lock && rm -rf node_modules && yarn && export BREAKING=yes && expo build:android --release-channel prod-v$npm_package_version --non-interactive",
    "upload-prod-android": "expo upload:android",
    "upload-prod-android-breaking": "export BREAKING=yes && expo upload:android",
    "expo-publish-dev": "expo publish --release-channel `python3 ./services/releaseChannel/getIssueIdFromBranchName.py`",
    "expo-publish-dev-breaking": "export BREAKING=yes && expo publish --release-channel `python3 ./services/releaseChannel/getIssueIdFromBranchName.py`",
    "expo-publish-prod": "expo publish --release-channel prod-v$npm_package_version",
    "expo-publish-prod-breaking": "export BREAKING=yes && expo publish --release-channel prod-v$npm_package_version",
    "locales:extract": "i18next-scanner --config i18next-scanner.config.js"
  },
  "dependencies": {
    "@emotion/native": "^11.0.0",
    "@emotion/react": "^11.1.1",
    "@react-native-async-storage/async-storage": "^1.13.0",
    "@react-native-community/checkbox": "^0.4.2",
    "@react-native-community/masked-view": "0.1.10",
    "@react-native-community/netinfo": "6.0.0",
    "@react-navigation/bottom-tabs": "^5.11.3",
    "@react-navigation/drawer": "^5.11.4",
    "@react-navigation/material-top-tabs": "^5.1.7",
    "@react-navigation/native": "^5.8.10",
    "@react-navigation/stack": "^5.12.8",
    "dayjs": "^1.10.4",
    "expo": "^41.0.0",
    "expo-camera": "~11.0.2",
    "expo-constants": "~10.1.3",
    "expo-document-picker": "~9.1.2",
    "expo-image-picker": "~10.1.4",
    "expo-media-library": "~12.0.2",
    "i18next": "^20.3.2",
    "i18next-scanner": "^3.0.0",
    "moment": "^2.26.0",
    "native-base": "^2.13.0",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-hook-form": "^7.5.2",
    "react-i18next": "^11.11.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
    "react-native-check-box": "^2.1.7",
    "react-native-elements": "^1.2.7",
    "react-native-floating-action": "^1.21.0",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-keyboard-aware-scroll-view": "^0.9.1",
    "react-native-picker-select": "^8.0.4",
    "react-native-reanimated": "~2.1.0",
    "react-native-responsive-screen": "^1.4.1",
    "react-native-screens": "~3.0.0",
    "react-native-svg": "12.1.0",
    "react-native-tab-view": "^2.13.0",
    "react-native-web": "~0.13.12",
    "react-navigation": "^4.0.5",
    "react-navigation-drawer": "^2.2.1",
    "react-navigation-stack": "^1.8.0",
    "react-navigation-tabs": "^2.5.3",
    "react-number-format": "^4.3.1",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5",
    "redux-form": "^8.3.6",
    "sentry-expo": "^3.1.0"
  },
  "devDependencies": {
    "@react-native-community/eslint-config": "^2.0.0",
    "babel-preset-expo": "8.3.0",
    "eslint": "^7.14.0",
    "eslint-plugin-react": "^7.24.0",
    "prettier": "^2.1.2",
    "standard-version": "^7.1.0",
    "standard-version-expo": "^1.0.3",
    "typescript": "~4.0.0"
  },
  "eslintConfig": {
    "extends": "@react-native-community",
    "plugins": [
      "react",
      "react-native",
      "react-hooks"
    ],
    "rules": {
      "camelcase": 1
    }
  },
  "private": true,
  "version": "2.2.10"
}

If I run yarn local:extract, this kind of keys are removed => t('common:content.detail', { count: 2 })

Expected behavior

I expected the default behavior, this means I expected to have two keys set in common.json, one for plural (with _plural as suffix) and one for singular.

Your Environment

  • runtime version: node v16.5.0
  • i18next version: v20.3.2
  • i18next-scanner version: v3.0.0
  • react-i18next version: v11.11.0
  • os: Mac
@shaftwin shaftwin changed the title bug: i18next-scanner is removing every translation key with plural version i18next-scanner is removing every translation key with plural version Sep 29, 2021
@shaftwin
Copy link
Author

shaftwin commented Oct 1, 2021

@cheton @daliusd I found what's going on, I18next jump to version 21.2.0 and it seems that i18next-scanner v3.0.0 plural feature is not working anymore.

I drop to i18next to version 20.3.2 and everything was back on track

@daliusd
Copy link
Contributor

daliusd commented Oct 1, 2021

I'm not maintainer of this project so I can't help in any way.

cheton added a commit that referenced this issue Oct 12, 2021
@cheton
Copy link
Member

cheton commented Oct 12, 2021

@shaftwin @daliusd
It's supposed to be resolved in PR #219 with the enforcement of i18next JSON v3

@cheton
Copy link
Member

cheton commented Oct 12, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants