l10n.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. module.metadata = {
  6. "stability": "stable"
  7. };
  8. const core = require("./l10n/core");
  9. const { getRulesForLocale } = require("./l10n/plural-rules");
  10. // Retrieve the plural mapping function
  11. let pluralMappingFunction = getRulesForLocale(core.language()) ||
  12. getRulesForLocale("en");
  13. exports.get = function get(k) {
  14. // For now, we only accept a "string" as first argument
  15. // TODO: handle plural forms in gettext pattern
  16. if (typeof k !== "string")
  17. throw new Error("First argument of localization method should be a string");
  18. // Get translation from big hashmap or default to hard coded string:
  19. let localized = core.get(k) || k;
  20. // # Simplest usecase:
  21. // // String hard coded in source code:
  22. // _("Hello world")
  23. // // Identifier of a key stored in properties file
  24. // _("helloString")
  25. if (arguments.length <= 1)
  26. return localized;
  27. let args = arguments;
  28. if (typeof localized == "object" && "other" in localized) {
  29. // # Plural form:
  30. // // Strings hard coded in source code:
  31. // _(["One download", "%d downloads"], 10);
  32. // // Identifier of a key stored in properties file
  33. // _("downloadNumber", 0);
  34. let n = arguments[1];
  35. // First handle simple universal forms that may not be mandatory
  36. // for each language, (i.e. not different than 'other' form,
  37. // but still usefull for better phrasing)
  38. // For example 0 in english is the same form than 'other'
  39. // but we accept 'zero' form if specified in localization file
  40. if (n === 0 && "zero" in localized)
  41. localized = localized["zero"];
  42. else if (n === 1 && "one" in localized)
  43. localized = localized["one"];
  44. else if (n === 2 && "two" in localized)
  45. localized = localized["two"];
  46. else {
  47. let pluralForm = pluralMappingFunction(n);
  48. if (pluralForm in localized)
  49. localized = localized[pluralForm];
  50. else // Fallback in case of error: missing plural form
  51. localized = localized["other"];
  52. }
  53. // Simulate a string with one placeholder:
  54. args = [null, n];
  55. }
  56. // # String with placeholders:
  57. // // Strings hard coded in source code:
  58. // _("Hello %s", username)
  59. // // Identifier of a key stored in properties file
  60. // _("helloString", username)
  61. // * We supports `%1s`, `%2s`, ... pattern in order to change arguments order
  62. // in translation.
  63. // * In case of plural form, we has `%d` instead of `%s`.
  64. let offset = 1;
  65. localized = localized.replace(/%(\d*)(s|d)/g, function (v, n) {
  66. let rv = args[n != "" ? n : offset];
  67. offset++;
  68. return rv;
  69. });
  70. return localized;
  71. }