npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wfh/translate-generator

v1.1.5

Published

A tool to scan source package files and generate translatable files

Downloads

5

Readme

This package is deprecated!


Text Translation & i18n

  • Package 结构 - 哪里存放i18n资源
  • 使用国际化文件资源
  • 全局配置文件config.yaml
  • 打包编译命令
  • 打包后的输出bundle目录结构
  • 客户端Javascript API,自动跳转不同语言页面]
  • 自动收集可翻译文字并生成可翻译文件的命令
    • 扫描的规则
  • 自动替换翻译的文字到不同的语言
  • NodeJS 端i18n

Package 结构 - 哪里存放i18n资源

为你的package添加本地化的文件,可以是各种能被require()的类型文件,比如.js, .json, .yaml, .yml, 统一放在一个目录下,推荐是 <package-folder>/i18n,这样大家可以达成共识,方便代码阅读。

package root folder
	├─ browser/
	├─ server/
	├─ i18n/
	|	├─ index.js
	|	├─ message-en.yaml
	|	├─ message-zh.yaml
	|	├─ message-zh-CN.yaml
	|	├─ feature-en.js
	|	├─ styles-en/
	|	|	├─ foobar.less
	|	... ...
	├─ README.md
	└─ package.json

文件名或者子目录名需要带有locale的标识,比如"en", "zh-CN"等。

使用国际化文件资源

e.g. JS files

require('<package-name>/i18n/message-{locale}.yaml');
require('./i18n/message-{locale}.yaml'); //可以相对路径
require('<package-name>/i18n/feature-{locale}.js');
require('./i18n/feature-{locale}.js'); //可以相对路径

LESS files

// LESS i18n resource的import 路径必须是"npm://<package-name>"开始,不能是相对路径
import "npm://<package-name>/i18n/foo-{locale}-bar.less";
import "npm://<package-name>/i18n/styles-{locale}/foobar.less";

{locale} 会在编译时被替换成相应的locale string 如"en", "zh"等,只要对应的文件路径是存在。

全局配置文件config.yaml

用来告诉我们的自动化可翻译文字扫描工具,已经drcp compile命令我们有多少locale语言当前支持
config.yaml文件

locales:
    - zh # 放在第一个的是默认locale
    - en

以上也是默认的配置,所以相应package如果支持i18n至少提供这些locale的文件。

打包编译命令

打包,并且用默认locale "zh" 替换所有JS, LESS中的require, import语句中的{locale}

drcp compile
# same as:
drcp compile --locale zh

打包,并且用非默认的locale "en" 替换所有JS, LESS中的require, import语句中的{locale}

drcp compile --locale en

所以当在开发环境drcp compile的实际编译目标仅仅是当前配置的默认locale。在生产环境时我们需要对多个locale分别执行多次打包命令。

打包后的输出bundle目录结构

默认locale的drcp compile输出的JS bundle, CSS bundle, 入口Html文件在 dist/static/下。非默认locale的JS bundle, CSS bundle, 入口Html文件在dist/static/<locale>下,e.g.

dist/
	└─ static/
		├─ js/
		├─ css/
		├─ foo-package/
		|		└─  index.Html
		├─ index.html
		└─ en/
			├─ js/
			├─ css/
			├─ foo-package/
			|		└─  index.Html
			└─ index.html

所以假设某个默认locale语言的页面访问路径是http://localhost:8080/foo-package/index.html,
对应非默认locale语言的(假设是"en")页面则是 http://localhost:8080/en/foo-package/index.html

客户端Javascript API,自动跳转不同语言页面

这些API可以帮助判断当前locale和为切换locale提供信息

var api = require('__api');
var lang = api.urlSearchParam().lang; // Get URL search param "lang"
lang = api.getPrefLanguage() // Get perferred language from Browser's user setting
var locales = api.config().locales; // Get all supported locale list from config.yaml
var currLocale = api.config().buildLocale; // Get current built-out locale

其中api.getPrefLanguage() 会根据浏览器语言设置匹配一个config.yaml locales中的一个, 浏览器语言的判断优先顺序是根据:

  • navigator.languages[0]
  • navigator.language
  • navigator.browserLanguage
  • navigator.systemLanguage
  • navigator.userLanguage
  • navigator.languages[1]

页面切换语言可以通过Server 端redirect URL地址或者,浏览器端HTML Anchor element, JS window.location=等跳转的方式实现, e.g. 切换"en"

简单的来说就是:

window.location='http://localhost:8080/en/foo-package/index.html';

或者一个更全面的API

var api = require('__api');
// If your web page runs inside DR company's mobile phone app
// We have a special component "@dr/dr-js-bridge" to work with language setting
var appInfo = require('@dr/dr-js-bridge').getAppInfo();
if (api.entryPackage === api.packageName) {
	// 确保在访问你的组件内的入口页面,做语言跳转,如果有时候你的组件正在
	// 被另一个组件当成library调用,这种情况不应该做语言切换
	var lang = appInfo.isCompanyApp || api.urlSearchParam().lang || api.getPrefLanguage();
	if (!api.reloadToLocale(lang)) // 如果当前页面语言不是首选语言 api.reloadToLocale 跳转到页面,并返true
		require('./browser.js');
} else {
	require('./browser.js');
}
var lang = api.urlSearchParam().lang || api.getPrefLanguage();
// Get URL parameter "?lang=<locale>" or Browser perferred language.
if (!api.reloadToLocale(lang)) {
	// If current page shows default language and the URL is like
	// "<staticAssetsURL>/pagePath", then we switch to target "lang" by
	// executing `window.location = "<staticAssetsURL>/<lang>/pagePath"`
	require('./main.js');
	// Render page and do business logic...
}

判断当前URL parameter “lang” 或浏览器首选语言, 如果当前页面是默认配置语言,切换到目标语言的URL上

如果是Node Server端, 可以通过Request "Accept-Language" header, redirect 到相应的URL

自动收集可翻译文字并生成可翻译文件的命令

使用translate-generator 工具

drcp compile <package-name..> --translate

扫描.js, .html 文件,自动生成可翻译的文件

	<package-dir>/i18n/
		├─ index.js
		├─ messages-en.yaml
		├─ messages-zh.yaml
		└─ ... other locale files in form of messages-{locale}.yaml

message-en.yaml里已经自动填满了message key, 从此你就不用手工为每个text label添加key到locale文件了。

扫描的规则

drcp compile --translate 会扫描指定package下的所有.js, .html文件

  • .html 文件,会使用cheerio 查找所有符合query [dr-translate], [t]的element, 也就是带有属性translate的element:

    <any-element dr-translate>KEY1</any-element>
    <any-element class="dr-translate">KEY2</any-element>
    <any-element t>KEY3</any-element>
    <any-element class="t">KEY4</any-element>

    class, attribute中有名为"t", "dr-translate"的element的html内容 KEY1KEY2都会被认为是locale message key。可以翻译的文字没有字符限制,比如可以是包含html, 甚至是AngularJS之类的浏览器端template engine

    <any-element dr-translate>Hellow <b>\{\{ name \}\}</b></any-element>

    Hellow <b>\{\{ name \}\}'</b> 整个都是key。

    另外是对可翻译HTML元素属性值的扫描 所有带有属性t-a="<attribute-name> <attribute-name> ..."的HTML element, 的指定属性(标注多个属性可以用空格或,间隔), <img alt>placeholder属性被默认为可以国际化翻译的值,不需要t-a=""的属性标注, 例如,

    <meta name="mymeta" content="translatableContent" t-a="content">
    <input type="text" placeholder="translatable"/>
    <img src="" alt="translatableAlt">

    以上例子中translatableContent, translatable, translatableAlt都会在扫描和打包时被提取出来作为可以翻译文字的key

    注意,i18n工具增强@dr/translate-generator是一个Webpack loader,对html, js[x]的处理方式是不同的,React JSX中的HTML被视为JS文件处理i18n, 目前被当成html处理t, t-a等特殊属性,该功能还为开发,鼓励贡献

  • .js 文件, 会在Acorn Javascript语法分析器生成的AST里查找function name是 drTranslate 的call expression, 第一个参数被识别收集为message key:

    drTranslate('KEY1');

    请不要使用其他的表达式作为drTranslate的参数, 只能使用String literal, 无法识别收集 如 drTranslate('foo' + 'bar' + x) 等复杂表达式,对于有特定format的表达式可以使用lodash template等方式,比如, _.template(drTranslate('foobar<%=x%>'))({x: x}) 将string模板作为可以翻译的文字

    除了drTranslate 还可以配置增加自定义的被扫描function name, 比如增加"myText()", 添加到config.yaml:

    translate-generator:
    	scanMethodNames:
    			- myText

自动替换翻译的文字到不同的语言

替换文件仅包括浏览器端Browserify会打包的JS + HTML bundle文件,entry page 文件,不包含NodeJS端的JS文件,或者是ExpressJS template HTML文件! 打包时替换可翻译文字的好处是,不会与Browser端framework template engine冲突,开发国际化更简单,对搜索引擎友好,对browser的性能没有损耗。

drcp compile [--locale <locale>] 时会替换所有Entry Page, JS文件中的 drTranslate('some text') html中<any-element class="t"></any-element> 等原先符合扫描收集规则的地方将会被替换为/i18n/message-{locale}.yaml所配置的内容,依然是通过Cheerio, Acorn来实现的。 e.g.

var text = drTranslate('中文');
doSomething(drTranslate('中文'));

替换后会是

var text = '中文';
doSomething('中文');

通过组件@dr/translate-generator, @dr-core/browserify-builder .addTransform()等实现的,简单的说就是Browserify的一个transform插件,有兴趣的可以自行扩展。

NodeJS 端i18n

需要自行实现,简单的说就是基于

require('./i18n/foobar-' + locale + '.js');