l10n.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. "use strict";
  2. // Small subset of the webL10n API by Fabien Cazenave for PDF.js extension.
  3. (function (window) {
  4. let gL10nData = null;
  5. let gLanguage = "";
  6. let gExternalLocalizerServices = null;
  7. let gReadyState = "loading";
  8. // fetch an l10n objects
  9. function getL10nData(key) {
  10. gL10nData ||= gExternalLocalizerServices.getStrings();
  11. const data = gL10nData?.[key];
  12. if (!data) {
  13. console.warn("[l10n] #" + key + " missing for [" + gLanguage + "]");
  14. }
  15. return data;
  16. }
  17. // replace {{arguments}} with their values
  18. function substArguments(text, args) {
  19. if (!args) {
  20. return text;
  21. }
  22. return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function (all, name) {
  23. return name in args ? args[name] : "{{" + name + "}}";
  24. });
  25. }
  26. // translate a string
  27. function translateString(key, args, fallback) {
  28. var i = key.lastIndexOf(".");
  29. var name, property;
  30. if (i >= 0) {
  31. name = key.substring(0, i);
  32. property = key.substring(i + 1);
  33. } else {
  34. name = key;
  35. property = "textContent";
  36. }
  37. var data = getL10nData(name);
  38. var value = (data && data[property]) || fallback;
  39. if (!value) {
  40. return "{{" + key + "}}";
  41. }
  42. return substArguments(value, args);
  43. }
  44. // translate an HTML element
  45. function translateElement(element) {
  46. if (!element || !element.dataset) {
  47. return;
  48. }
  49. // get the related l10n object
  50. var key = element.dataset.l10nId;
  51. var data = getL10nData(key);
  52. if (!data) {
  53. return;
  54. }
  55. // get arguments (if any)
  56. // TODO: more flexible parser?
  57. var args;
  58. if (element.dataset.l10nArgs) {
  59. try {
  60. args = JSON.parse(element.dataset.l10nArgs);
  61. } catch (e) {
  62. console.warn("[l10n] could not parse arguments for #" + key + "");
  63. }
  64. }
  65. // translate element
  66. // TODO: security check?
  67. for (var k in data) {
  68. element[k] = substArguments(data[k], args);
  69. }
  70. }
  71. // translate an HTML subtree
  72. function translateFragment(element) {
  73. element = element || document.querySelector("html");
  74. // check all translatable children (= w/ a `data-l10n-id' attribute)
  75. var children = element.querySelectorAll("*[data-l10n-id]");
  76. var elementCount = children.length;
  77. for (var i = 0; i < elementCount; i++) {
  78. translateElement(children[i]);
  79. }
  80. // translate element itself if necessary
  81. if (element.dataset.l10nId) {
  82. translateElement(element);
  83. }
  84. }
  85. // Public API
  86. document.mozL10n = {
  87. // get a localized string
  88. get: translateString,
  89. // get the document language
  90. getLanguage() {
  91. return gLanguage;
  92. },
  93. // get the direction (ltr|rtl) of the current language
  94. getDirection() {
  95. // http://www.w3.org/International/questions/qa-scripts
  96. // Arabic, Hebrew, Farsi, Pashto, Urdu
  97. var rtlList = ["ar", "he", "fa", "ps", "ur"];
  98. // use the short language code for "full" codes like 'ar-sa' (issue 5440)
  99. var shortCode = gLanguage.split("-")[0];
  100. return rtlList.includes(shortCode) ? "rtl" : "ltr";
  101. },
  102. getReadyState() {
  103. return gReadyState;
  104. },
  105. setExternalLocalizerServices(externalLocalizerServices) {
  106. gExternalLocalizerServices = externalLocalizerServices;
  107. gLanguage = gExternalLocalizerServices.getLocale();
  108. gReadyState = "complete";
  109. },
  110. // translate an element or document fragment
  111. translate: translateFragment,
  112. };
  113. })(this);