app.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. 'use strict';
  2. const locales = require('koa-locales');
  3. const fs = require('fs');
  4. const path = require('path');
  5. const debug = require('debug')('egg:plugin:i18n');
  6. /**
  7. * I18n 国际化
  8. *
  9. * 通过设置 Plugin 配置 `i18n: true`,开启多语言支持。
  10. *
  11. * #### 语言文件存储路径
  12. *
  13. * 统一存放在 `config/locale/*.js` 下( 兼容`config/locales/*.js` ),如包含英文,简体中文,繁体中文的语言文件:
  14. *
  15. * ```
  16. * - config/locale/
  17. * - en-US.js
  18. * - zh-CN.js
  19. * - zh-TW.js
  20. * ```
  21. * @class I18n
  22. * @param {App} app Application object.
  23. * @example
  24. *
  25. * #### I18n 文件内容
  26. *
  27. * ```js
  28. * // config/locale/zh-CN.js
  29. * module.exports = {
  30. * "Email": "邮箱",
  31. * "Welcome back, %s!": "欢迎回来, %s!",
  32. * "Hello %s, how are you today?": "你好 %s, 今天过得咋样?",
  33. * };
  34. * ```
  35. *
  36. * ```js
  37. * // config/locale/en-US.js
  38. * module.exports = {
  39. * "Email": "Email",
  40. * };
  41. * ```
  42. * 或者也可以用 JSON 格式的文件:
  43. *
  44. * ```js
  45. * // config/locale/zh-CN.json
  46. * {
  47. * "email": "邮箱",
  48. * "login": "帐号",
  49. * "createdAt": "注册时间"
  50. * }
  51. * ```
  52. */
  53. module.exports = app => {
  54. /**
  55. * 如果开启了 I18n 多语言功能,那么会出现此 API,通过它可以获取到当前请求对应的本地化数据。
  56. *
  57. * 详细使用说明,请查看 {@link I18n}
  58. * - `ctx.__ = function (key, value[, value2, ...])`: 类似 `util.format` 接口
  59. * - `ctx.__ = function (key, values)`: 支持数组下标占位符方式,如
  60. * - `__` 的别名是 `gettext(key, value)`
  61. *
  62. * > NOTE: __ 是两个下划线哦!
  63. * @method Context#__
  64. * @example
  65. * ```js
  66. * ctx.__('{0} {0} {1} {1}'), ['foo', 'bar'])
  67. * ctx.gettext('{0} {0} {1} {1}'), ['foo', 'bar'])
  68. * =>
  69. * foo foo bar bar
  70. * ```
  71. * ##### Controller 下的使用示例
  72. *
  73. * ```js
  74. * module.exports = function* () {
  75. * this.body = {
  76. * message: this.__('Welcome back, %s!', this.user.name),
  77. * // 或者使用 gettext,如果觉得 __ 不好看的话
  78. * // message: this.gettext('Welcome back, %s!', this.user.name),
  79. * user: this.user,
  80. * };
  81. * };
  82. * ```
  83. *
  84. * ##### View 文件下的使用示例
  85. *
  86. * ```html
  87. * <li>{{ __('Email') }}: {{ user.email }}</li>
  88. * <li>
  89. * {{ __('Hello %s, how are you today?', user.name) }}
  90. * </li>
  91. * <li>
  92. * {{ __('{0} {0} {1} {1}'), ['foo', 'bar']) }}
  93. * </li>
  94. * ```
  95. *
  96. * ##### locale 参数获取途径
  97. *
  98. * 优先级从上到下:
  99. *
  100. * - query: `/?locale=en-US`
  101. * - cookie: `locale=zh-TW`
  102. * - header: `Accept-Language: zh-CN,zh;q=0.5`
  103. */
  104. app.config.i18n.functionName = '__';
  105. /* istanbul ignore next */
  106. app.config.i18n.dirs = Array.isArray(app.config.i18n.dirs) ? app.config.i18n.dirs : [];
  107. // 按 egg > 插件 > 框架 > 应用的顺序遍历 config/locale(config/locales) 目录,加载所有配置文件
  108. for (const unit of app.loader.getLoadUnits()) {
  109. const localePath = path.join(unit.path, 'config/locale');
  110. /**
  111. * 优先选择 `config/locale` 目录下的多语言文件
  112. * 避免 2 个目录同时存在时可能导致的冲突
  113. */
  114. if (fs.existsSync(localePath)) {
  115. app.config.i18n.dirs.push(localePath);
  116. } else {
  117. app.config.i18n.dirs.push(path.join(unit.path, 'config/locales'));
  118. }
  119. }
  120. debug('app.config.i18n.dirs:', app.config.i18n.dirs);
  121. locales(app, app.config.i18n);
  122. /**
  123. * `ctx.__` 的别名。
  124. * @see {@link Context#__}
  125. * @method Context#gettext
  126. */
  127. app.context.gettext = app.context.__;
  128. // 自动加载 Middleware
  129. app.config.coreMiddleware.push('i18n');
  130. };