We planned to upgrade GitLab and Mattermost to the latest version this Friday morning (early). You may experience some downtime!

Commit 523c9065 authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg Committed by Sébastiaan Versteeg

Add localisation using i18next and i18next-scanner

parent 06582c29
......@@ -145,6 +145,7 @@ android {
}
dependencies {
compile project(':react-native-locale-detector')
compile project(':react-native-snackbar')
compile project(':react-native-fcm')
compile project(':react-native-linear-gradient')
......
......@@ -4,6 +4,7 @@ import android.app.Application;
import com.facebook.react.ReactApplication;
import com.azendoo.reactnativesnackbar.SnackbarPackage;
import com.i18n.reactnativei18n.ReactNativeI18n;
import com.evollu.react.fcm.FIRMessagingPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.oblador.vectoricons.VectorIconsPackage;
......@@ -26,8 +27,9 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new MainReactPackage(),
new SnackbarPackage(),
new ReactNativeI18n(),
new FIRMessagingPackage(),
new LinearGradientPackage(),
new VectorIconsPackage()
......
rootProject.name = 'ThaliApp'
include ':react-native-snackbar'
project(':react-native-snackbar').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-snackbar/android')
include ':react-native-locale-detector'
project(':react-native-locale-detector').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-locale-detector/android')
include ':react-native-fcm'
project(':react-native-fcm').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fcm/android')
include ':react-native-linear-gradient'
......
......@@ -6,8 +6,11 @@ import createSagaMiddleware from 'redux-saga';
import FCM, { FCMEvent } from 'react-native-fcm';
import Moment from 'moment';
import 'moment/locale/nl';
import { I18nextProvider } from 'react-i18next';
import * as reducers from './reducers';
import i18n from './i18n';
import sagas from './sagas';
import ReduxNavigator from './components/navigator';
import * as loginActions from './actions/login';
......@@ -91,9 +94,11 @@ class Main extends Component {
render() {
return (
<Provider store={store}>
<ReduxNavigator />
</Provider>
<I18nextProvider i18n={i18n}>
<Provider store={store}>
<ReduxNavigator />
</Provider>
</I18nextProvider>
);
}
}
......
import i18n from 'i18next';
import { reactI18nextModule } from 'react-i18next';
import i18nextReactNative from 'i18next-react-native-language-detector';
import locales from './locales/index';
i18n
.use(reactI18nextModule)
.use(i18nextReactNative)
.init({
nsSeparator: false,
keySeparator: false,
fallbackLng: 'nl',
resources: locales,
interpolation: {
escapeValue: false, // not needed for react!!
},
});
export default i18n;
/* eslint-disable import/no-extraneous-dependencies */
const Parser = require('i18next-scanner').Parser;
const fs = require('fs');
const path = require('path');
const componentsPath = 'app/components';
const options = {
nsSeparator: false,
keySeparator: false,
sort: true,
lngs: ['nl'],
func: {
list: ['t'],
},
defaultNs: 'test',
removeUnusedKeys: true,
resource: {
loadPath: 'app/locales/{{lng}}/{{ns}}.json',
savePath: 'app/locales/{{lng}}/{{ns}}.json',
},
};
const indexFiles = {};
options.lngs.forEach((lang) => {
indexFiles[lang] = [];
});
const components = fs.readdirSync(componentsPath).filter(f =>
fs.statSync(path.join(componentsPath, f)).isFile());
components.forEach((f) => {
options.defaultNs = f.substr(0, 1).toLowerCase() + f.substr(1, f.length - 4);
const parser = new Parser(options);
const content = fs.readFileSync(path.join(componentsPath, f), 'utf-8');
parser.parseFuncFromString(content);
parser.parseTransFromString(content);
const resStore = parser.get();
Object.keys(resStore).forEach((lng) => {
const namespaces = resStore[lng];
Object.keys(namespaces).forEach((ns) => {
const obj = namespaces[ns];
const resPath = parser.formatResourceSavePath(lng, ns);
if (Object.keys(obj).length > 0) {
const str = JSON.stringify(obj, null, 2);
const dir = path.dirname(resPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
fs.writeFileSync(resPath, `${str}\n`);
indexFiles[lng].push(ns);
} else if (fs.existsSync(resPath)) {
fs.unlinkSync(resPath);
}
});
});
});
const indexStream = fs.createWriteStream('app/locales/index.js');
indexStream.once('open', () => {
Object.keys(indexFiles).forEach((lang) => {
const files = indexFiles[lang];
const langName = lang.toUpperCase();
files.forEach((fileName) => {
indexStream.write(`const ${fileName}${langName} = require('./${lang}/${fileName}.json');\n`);
});
});
indexStream.write('\n');
indexStream.write('export default {\n');
Object.keys(indexFiles).forEach((lang) => {
indexStream.write(` ${lang}: {\n`);
const files = indexFiles[lang];
const langName = lang.toUpperCase();
files.forEach((fileName) => {
indexStream.write(` ${fileName}: ${fileName}${langName},\n`);
});
indexStream.write(' },\n');
});
indexStream.write('};\n');
indexStream.end();
});
......@@ -444,6 +444,11 @@
F80608CE5FD849848A5498D4 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; };
F808FC5B0C6A43748E179BF6 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
FF381FFBF70744E6865413C2 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
8AB867AF03AC45AEB3C80BFA /* RNSnackbar.xcodeproj */ = {isa = PBXFileReference; name = "RNSnackbar.xcodeproj"; path = "../node_modules/react-native-snackbar/ios/RNSnackbar.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
290659E890FD4B2CB58F9F15 /* libRNSnackbar.a */ = {isa = PBXFileReference; name = "libRNSnackbar.a"; path = "libRNSnackbar.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
F80608CE5FD849848A5498D4 /* Feather.ttf */ = {isa = PBXFileReference; name = "Feather.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
0E27F218F14040B7AFFA10E0 /* RNI18n.xcodeproj */ = {isa = PBXFileReference; name = "RNI18n.xcodeproj"; path = "../node_modules/react-native-locale-detector/RNI18n.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
4ED63341CE1E457597AA80EB /* libRNI18n.a */ = {isa = PBXFileReference; name = "libRNI18n.a"; path = "libRNI18n.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -487,6 +492,7 @@
D9076E5B3D6E539979F86BE7 /* AVFoundation.framework in Frameworks */,
A64C779AE827706A1A3A8C53 /* CoreMedia.framework in Frameworks */,
E9012CD6A7C0147AFA3AE7C9 /* CoreVideo.framework in Frameworks */,
2EEA998D004342DD928F8C45 /* libRNI18n.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -724,6 +730,7 @@
5A90BA3FF7F8422A9150FDAA /* BVLinearGradient.xcodeproj */,
8CED7FC8420844AF92491FE8 /* RNFIRMessaging.xcodeproj */,
8AB867AF03AC45AEB3C80BFA /* RNSnackbar.xcodeproj */,
0E27F218F14040B7AFFA10E0 /* RNI18n.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
......@@ -1574,6 +1581,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = ThaliAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
......@@ -1608,6 +1616,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = ThaliAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
......@@ -1649,6 +1658,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = ThaliApp/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......@@ -1682,6 +1692,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = ThaliApp/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......@@ -1714,6 +1725,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = "ThaliApp-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......@@ -1754,6 +1766,7 @@
"$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
"$(SRCROOT)/../node_modules/react-native-snackbar/ios",
"$(SRCROOT)/../node_modules/react-native-locale-detector/RNI18n",
);
INFOPLIST_FILE = "ThaliApp-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......
......@@ -12,7 +12,8 @@
"lint:ci": "eslint *.js app",
"test": "jest",
"test:watch": "jest --watch",
"coverage": "jest --coverage"
"coverage": "jest --coverage",
"locales:collect": "node collect-locales.js"
},
"jest": {
"preset": "react-native",
......@@ -29,6 +30,8 @@
]
},
"dependencies": {
"i18next": "^10.0.3",
"i18next-react-native-language-detector": "^1.0.2",
"moment": "^2.18.1",
"prop-types": "^15.5.8",
"react": "16.2.0",
......@@ -37,6 +40,8 @@
"react-native-fcm": "^10.0.2",
"react-native-linear-gradient": "^2.0.0",
"react-native-snackbar": "^0.4.3",
"react-i18next": "^6.0.6",
"react-native-locale-detector": "^1.0.1",
"react-native-vector-icons": "^4.0.1",
"react-redux": "^5.0.2",
"redux": "^3.6.0",
......@@ -53,6 +58,7 @@
"eslint-plugin-jsx-a11y": "^3.0.2",
"eslint-plugin-react": "^6.9.0",
"eslint-plugin-react-native": "^2.2.1",
"i18next-scanner": "^2.0.0",
"jest": "^19.0.2",
"react-native-cli": "^2.0.1",
"react-native-git-upgrade": "^0.2.7",
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment