multiple-language-redirect.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright 2023 Apollo Authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. /*
  18. * A custom docsify plugin. Let user switch to another language more convenient.
  19. * Reference https://docsify.js.org/#/write-a-plugin
  20. *
  21. * @author wxq
  22. */
  23. /* JavaScript's function below */
  24. function findCurrentLanguagePrefix(languagePrefixs, path) {
  25. languagesPrefixOrderByLengthDesc = languagePrefixs.sort(function (a, b) {
  26. return b.length - a.length;
  27. })
  28. for (const languagePrefix of languagesPrefixOrderByLengthDesc) {
  29. if (path.startsWith(languagePrefix)) {
  30. return languagePrefix;
  31. }
  32. }
  33. console.error("cannot find language prefix in path", path, "through", languagePrefixs)
  34. return '/';
  35. }
  36. function generateLanguagePrefix2Path(languagePrefixs, path) {
  37. const currentLanguagePrefix = findCurrentLanguagePrefix(languagePrefixs, path);
  38. languagePrefix2Path = {};
  39. for (const targetLanguagePrefix of languagesPrefixOrderByLengthDesc) {
  40. languagePrefix2Path[targetLanguagePrefix] = path.replace(currentLanguagePrefix, targetLanguagePrefix);
  41. }
  42. return languagePrefix2Path;
  43. }
  44. /**
  45. * find list item in navbar by its name.
  46. */
  47. function findTranslationsListItem(translationsListItemName) {
  48. const nav = document.querySelector("nav");
  49. if (null == nav) {
  50. return null;
  51. }
  52. const ul = nav.querySelector("ul");
  53. if (null == ul) {
  54. return null;
  55. }
  56. const listItems = ul.querySelectorAll("li");
  57. if (null == listItems) {
  58. return null;
  59. }
  60. for (const listItem of listItems) {
  61. if (listItem.innerText.includes(translationsListItemName)) {
  62. return listItem;
  63. }
  64. }
  65. return null;
  66. }
  67. function walkElementInTranslationsListItem(translationsListItem, elementName, visitor) {
  68. const elements = translationsListItem.querySelectorAll(elementName);
  69. for (const element of elements) {
  70. visitor(element);
  71. }
  72. }
  73. function removeSharpPrefixInHref(href) {
  74. if (href.startsWith("#")) {
  75. // delete '#' in prefix, example: '#/zh-cn/' => '/zh-cn/'
  76. return href.substring(1);
  77. } else {
  78. return href;
  79. }
  80. }
  81. function addSharpToPrefix(path) {
  82. if (path.startsWith("#")) {
  83. return path;
  84. } else {
  85. return "#" + path;
  86. }
  87. }
  88. /**
  89. * find language which user config in '_navbar.md'.
  90. *
  91. * @returns a list of language prefix config in '_navbar.md'
  92. */
  93. function resolveLanguagePrefixsFromListItem(translationsListItem) {
  94. languagePrefixs = []
  95. walkElementInTranslationsListItem(translationsListItem, 'a', function (aElement) {
  96. const href = aElement.getAttribute("href");
  97. languagePrefix = removeSharpPrefixInHref(href);
  98. languagePrefixs.push(languagePrefix);
  99. });
  100. // a return example: ['/', '/zh-cn/', '/de-de/', '/es/', '/ru-ru/']
  101. return languagePrefixs;
  102. }
  103. function changeLinkInTranslationsListItem(currrentPath, translationsListItem) {
  104. const languagePrefixs = resolveLanguagePrefixsFromListItem(translationsListItem);
  105. const languagePrefix2Path = generateLanguagePrefix2Path(languagePrefixs, currrentPath);
  106. walkElementInTranslationsListItem(translationsListItem, 'a', function (aElement) {
  107. const href = aElement.getAttribute("href");
  108. const languagePrefix = removeSharpPrefixInHref(href);
  109. const newPath = languagePrefix2Path[languagePrefix];
  110. const newHref = addSharpToPrefix(newPath);
  111. aElement.setAttribute("href", newHref);
  112. // console.log(href, "=>", newHref);
  113. });
  114. }
  115. /**
  116. * When user click another language in navbar's Translations,
  117. * website's path will change to path which corresponding to current language.
  118. * @param {string} name item name 'Translations' in navbar
  119. */
  120. function generateMultipleLanguagesNavbarPluginByListItemName(name) {
  121. return function (hook, vm) {
  122. const bindEventForChangeHrefInNavbar = () => {
  123. // when user's mouse down, chanage href in navbar
  124. document.addEventListener("mousedown", _mouseEvent => {
  125. const currrentPath = vm.route.path;
  126. // find navbar list item by hard code name
  127. const translationsListItemName = name;
  128. const translationsListItem = findTranslationsListItem(translationsListItemName);
  129. if (null == translationsListItem) {
  130. console.warn("there is no navbar or ", translationsListItemName, "in current path", currrentPath);
  131. } else {
  132. changeLinkInTranslationsListItem(currrentPath, translationsListItem);
  133. }
  134. });
  135. };
  136. hook.init(bindEventForChangeHrefInNavbar);
  137. };
  138. }