├── .npmignore ├── static ├── vue.png ├── react.png ├── angular.png └── browserify.png ├── .github └── FUNDING.yml ├── src ├── main.js └── LanguageLocator.js ├── package.json ├── LICENSE ├── .gitignore └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | static -------------------------------------------------------------------------------- /static/vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/i18n-js-npm/HEAD/static/vue.png -------------------------------------------------------------------------------- /static/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/i18n-js-npm/HEAD/static/react.png -------------------------------------------------------------------------------- /static/angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/i18n-js-npm/HEAD/static/angular.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [atapas] 4 | -------------------------------------------------------------------------------- /static/browserify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/i18n-js-npm/HEAD/static/browserify.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Created on Tue May 12 2020 4 | * 5 | * Copyright (c) 2020 https://tapasadhikary.com 6 | */ 7 | 8 | module.exports = require('./LanguageLocator.js'); 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "i18n-web", 3 | "version": "0.0.4", 4 | "description": "A simple tool helps in externalizing the strings in a JavaScript Application. It has the additional capability of parameterizing the strings.", 5 | "main": "src/main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/atapas/i18n-js-npm.git" 12 | }, 13 | "keywords": [ 14 | "intl", 15 | "i18n", 16 | "internationalization", 17 | "locale", 18 | "translate", 19 | "translation", 20 | "javascript", 21 | "react", 22 | "angular", 23 | "vue", 24 | "web" 25 | ], 26 | "author": "Tapas Adhikary", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/atapas/i18n-js-npm/issues" 30 | }, 31 | "homepage": "https://github.com/atapas/i18n-js-npm#readme" 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Tapas Adhikary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/LanguageLocator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Tue May 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | 8 | import * as Langs from '../../../i18n/index.js'; 9 | 10 | 11 | let clientPrimaryLang = navigator.languages[0]; 12 | 13 | let matchedLang = clientPrimaryLang.indexOf('-') > 0 ? 14 | clientPrimaryLang.substring(0, clientPrimaryLang.indexOf('-')) : 15 | clientPrimaryLang; 16 | 17 | console.log(matchedLang); 18 | 19 | const replaceParams = (replaced, ...params) => { 20 | params.forEach((item, index) => { 21 | let match = new RegExp(`\\{${index}\\}`); 22 | replaced = replaced.replace(match, item); 23 | }); 24 | return replaced; 25 | } 26 | 27 | const i18n = (key, ...params) => { 28 | console.log(params); 29 | let value = ''; 30 | 31 | if (Langs[matchedLang]) { 32 | if (key.indexOf('.') > 0) { 33 | // Support nested key 34 | value = Langs[matchedLang][key.split('.')[0]][key.split('.')[1]]; 35 | } else { 36 | value = Langs[matchedLang][key]; 37 | } 38 | } else { 39 | // If the user preferred language is not supported, 40 | // fallback to english('en') 41 | if (key.indexOf('.') > 0) { 42 | // Support nested key 43 | value = Langs['en'][key.split('.')[0]][key.split('.')[1]]; 44 | } else { 45 | value = Langs['en'][key]; 46 | } 47 | } 48 | 49 | let replaced = value; 50 | if (params && params.length > 0) { 51 | // replace {0}, {1} etc with param 1 and param 2 52 | replaced = replaceParams(replaced, ...params); 53 | } 54 | return replaced; 55 | }; 56 | 57 | export default i18n; 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i18n-web 2 | 3 | `i18n-web` is a simple tool helps in externalizing the strings in a JavaScript based Application such that, Internationalization(i18n) can be achieved easily. It has the additional capability of parameterizing the strings to get the dynamic content Internationalized. 4 | 5 | # Install 6 | 7 | - Using yarn: `yarn add i18n-web` 8 | - Using npm: `npm install i18n-web` 9 | 10 | # What is String Externalization? 11 | String Externalization means, instead of writing the user(or customer) facing strings in source files(.html, .js, .java etc), we keep them in an external file like .properties, .json etc and load from there. This is to help Internationalization (i18n). 12 | 13 | # What is Internationalization (i18n)? 14 | In Software, Internationalization (i18n) is the process to support various local languages like, English(en), Spanish(es), German(de) etc. 15 | 16 | All the browsers come with the in-built support of languages which can be used to identify the local language to support for the application. 17 | 18 | # How String Externalization help in Internationalization (i18n) of the Web Applications? 19 | A Web Application may have the need of supporting multiple languages based on the targeted users. If the Application Strings are Externalized outside of the source files, it is easy and flexible to support i18n. 20 | 21 | Lets consider, all the application strings are in a file called `en.json` and this file can be loaded into the application to retrieve the strings when the app is running in English Language. 22 | 23 | ```js 24 | { 25 | 'username': 'User Name', 26 | 'password': 'Password', 27 | 'hasBlog': '{0} has a blog named, {1}. This is on {2}.' 28 | } 29 | ``` 30 | 31 | Now there could be equivalent `es.json` file which can be loaded into the application when browser supported language is Spanish instead of English. 32 | 33 | ```js 34 | { 35 | 'username': 'Nombre de usuario', 36 | 'password': 'Contraseña', 37 | 'hasBlog': '{0} tiene un blog llamado {1}. Esto está en {2}.' 38 | } 39 | ``` 40 | 41 | # i18n-web Usage 42 | 43 | ## Basic Setup and Structure 44 | 45 | The tool `i18n-web` helps in externalizing the string and thus, internationalizing your web app with few quick and easy steps. 46 | 47 | - Create a folder called `i18n` at the same level of `node_modules` folder of your app. 48 | - Create `en.js`, `es.js`, `de.js` etc file to contain your application specific strings externalized. You must add all required language .js files that your app would support. 49 | 50 | Here is an example of the en.js and es.js file. 51 | 52 | ```js 53 | // en.js 54 | const en = { 55 | 'username': 'User Name', 56 | 'password': 'Password', 57 | 'hasBlog': '{0} has a blog named, {1}. This is on {2}.' 58 | } 59 | 60 | export { en }; 61 | ``` 62 | 63 | ```js 64 | // es.js 65 | const es = { 66 | 'username': 'Nombre de usuario', 67 | 'password': 'Contraseña', 68 | 'hasBlog': '{0} tiene un blog llamado {1}. Esto está en {2}.' 69 | } 70 | 71 | export { es }; 72 | ``` 73 | 74 | - Create another file called, `index.js` where you can aggregate the all modules and export together like this: 75 | 76 | ```js 77 | export { en } from './en.js'; 78 | export { es } from './es.js'; 79 | ``` 80 | 81 | Example Directory Structure: 82 | 83 | ``` 84 | myapp 85 | └── i18n 86 | └── en.js 87 | └── es.js 88 | └── de.js 89 | └── fr.js 90 | └── index.js 91 | └── node_modules 92 | ``` 93 | 94 | ## Using it in UI Code 95 | 96 | - In your UI Code, import it as, 97 | 98 | ```js 99 | import i18n from 'i18n-web'; 100 | ``` 101 | 102 | - Use it like: 103 | 104 | ```js 105 | // When no parameters. Just Key is passed 106 | console.log(i18n('usename')); 107 | 108 | // Output: 109 | 110 | // 'User Name' for English 111 | 112 | // 'Nombre de usuario' for Spanish 113 | 114 | ``` 115 | 116 | ```js 117 | // With parameters. 118 | const params = ['Tapas', 'greenroos', 'JavaScript']; 119 | let hasBlog = i18n('hasBlog', ...params); 120 | console.log(hasBlog); 121 | 122 | // Output: 123 | 124 | // 'Tapas has a blog named, greenroots. This is on JavaScript.' for English and 125 | 126 | // 'Tapas tiene un blog llamado greenroots. Esto está en JavaScript.' for Spanish 127 | ``` 128 | 129 | # Tested with 130 | 131 | [](https://angular.io/) 132 | [](https://reactjs.org/) 133 | [](https://vuejs.org/) 134 | [](http://browserify.org/) 135 | 136 | 137 | --------------------------------------------------------------------------------