i18n.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. const { vsprintf } = require('sprintf-js');
  3. function i18n(options = {}) {
  4. this.data = {};
  5. this.languages = options.languages || ['default'];
  6. if (!Array.isArray(this.languages)) {
  7. this.languages = [this.languages];
  8. }
  9. }
  10. i18n.prototype.get = function(languages) {
  11. const { data } = this;
  12. const result = {};
  13. if (languages) {
  14. if (!Array.isArray(languages)) {
  15. languages = [languages];
  16. }
  17. } else {
  18. languages = this.languages;
  19. }
  20. for (let i = 0, leni = languages.length; i < leni; i++) {
  21. const lang = languages[i];
  22. const langData = data[lang];
  23. if (!langData) continue;
  24. const keys = Object.keys(langData);
  25. for (let j = 0, lenj = keys.length; j < lenj; j++) {
  26. const key = keys[j];
  27. if (!Object.prototype.hasOwnProperty.call(result, key)) result[key] = langData[key];
  28. }
  29. }
  30. return result;
  31. };
  32. i18n.prototype.set = function(lang, data) {
  33. if (typeof lang !== 'string') throw new TypeError('lang must be a string!');
  34. if (typeof data !== 'object') throw new TypeError('data is required!');
  35. this.data[lang] = flattenObject(data);
  36. return this;
  37. };
  38. i18n.prototype.remove = function(lang) {
  39. if (typeof lang !== 'string') throw new TypeError('lang must be a string!');
  40. delete this.data[lang];
  41. return this;
  42. };
  43. i18n.prototype.list = function() {
  44. return Object.keys(this.data);
  45. };
  46. function flattenObject(data, obj = {}, parent = '') {
  47. const keys = Object.keys(data);
  48. for (let i = 0, len = keys.length; i < len; i++) {
  49. const key = keys[i];
  50. const item = data[key];
  51. if (typeof item === 'object') {
  52. flattenObject(item, obj, parent + key + '.');
  53. } else {
  54. obj[parent + key] = item;
  55. }
  56. }
  57. return obj;
  58. }
  59. i18n.prototype.__ = function(lang) {
  60. const data = this.get(lang);
  61. return (key, ...args) => {
  62. if (!key) return '';
  63. const str = data[key] || key;
  64. return vsprintf(str, args);
  65. };
  66. };
  67. i18n.prototype._p = function(lang) {
  68. const data = this.get(lang);
  69. return (key, ...args) => {
  70. if (!key) return '';
  71. const number = args.length ? +args[0] : 0;
  72. let str = key;
  73. if (!number && Object.prototype.hasOwnProperty.call(data, key + '.zero')) {
  74. str = data[key + '.zero'];
  75. } else if (number === 1 && Object.prototype.hasOwnProperty.call(data, key + '.one')) {
  76. str = data[key + '.one'];
  77. } else if (Object.prototype.hasOwnProperty.call(data, key + '.other')) {
  78. str = data[key + '.other'];
  79. } else if (Object.prototype.hasOwnProperty.call(data, key)) {
  80. str = data[key];
  81. }
  82. return vsprintf(str, args);
  83. };
  84. };
  85. module.exports = i18n;