奥克兰软件开发公司|我们的前端开发工程师John分享如何让如何國際化(i18n)您的网站,多语言的网站可以让新西兰西人和华人都能找得到

大家好,奥克兰软件开发公司local fern的前端开发工程师John~,在这篇文章中,我们将会使用preact-i18n来国际化您的react项目。多语言的网站可以让新西兰西人和华人都能找得到

步骤 1:设置Preact CLI, 并创建一个新的项目

注: 如果您已经熟悉Preact了,您可以跳到下一步。

如果您还没有将Preact CLI安装到您的电脑,请使用以下的命令来安装Preact CLI。这CLI需要Node.js 版本 6.x 或以上。
$ npm install -g preact-cli


当您已经成功将Preact CLI安装到您的电脑中,我们将会使用以下的命令来创建一个名为my-project的项目。在这个项目中,我们将会使用default模板。
$ preact create default my-project


之后呢,您可以使用以下的命令来启动本地测试服务器。
$ cd my-project && npm run start


这个时候,我们需要打开我们的游览器,并前往http://localhost:8080, 你将会看到像这样类似的画面:




步骤 2:安装preact-18n

我们将会使用以下的命令来安装preact-i18n到您的项目中。
$ npm install --save preact-i18n


preact-i18n是非常容易使用的。更重要的是, 这preact-i18n在gzip之后才占据不到1.3kb的大小。

步骤 3:创建definition文件

当你已将preact-i18n安装到您的项目之后,我们将会创建一个definition文件。我们将会把我们要翻译的文字和句子,储存在这个JSON文件中。

我们将会把这个definition文件储存在src/i18n/zh-tw.json。
{ 
\"home\": {
\"title\": \"主页\",
\"text\": \"这是个Home组件。\"
}
}



步骤 4:导入IntlProvider及definition文件

接下来,我们将会从src/components中打开app.js。我们将会在这个文件中导入IntlProvider及definition文件。
import { IntlProvider } from \'preact-i18n\';
import definition from \'../i18n/zh-tw.json\';



步骤 5:把IntlProvider放在项目中最高层级的组件

然后呢,我们将会在把<IntlProvider>放在项目中最高层级的组件,也就是我们的app.js。这样子,我们就能在这Preact项目中的任何一个组件中读取到definition文件。
render() {
return(
<IntlProvider definition={definition}>
<div id=\"app\" />
</IntlProvider>
);
}



在这个时候,您的app.js文件的内容应该是要跟以下的例子类似:
import { h, Component } from \'preact\';
import { Router } from \'preact-router\';
import Header from \'./header\';
import Home from \'../routes/home\';
import Profile from \'../routes/profile\';
// 导入 IntlProvider 及 definition 文件。
import { IntlProvider } from \'preact-i18n\';
import definition from \'../i18n/zh-tw.json\';
export default class App extends Component {

handleRoute = e => {
this.currentUrl = e.url;
};
render() {
return (
// 把 <IntlProvider> 放在项目中最高层级的组件
<IntlProvider definition={definition}>
<div id=\"app\">
<Header />
<Router onChange={this.handleRoute}>
<Home path=\"/\" />
<Profile path=\"/profile/\" user=\"me\" />
<Profile path=\"/profile/:user\" />
</Router>
</div>
</IntlProvider>
);
}
}




步骤 6:使用Text来显示翻译字符串文字
 

我们只差一步就成功了。在以下的例子中,我们将会翻译主页(src/routes/home/index.js)中所有的文字。现在,我们只需要把网页中的字改成<Text>。因此,我们将会把<Text>添加进<h1>和<p>里。
import { Text } from \'preact-i18n\';
const Home = () => (
<div>
<h1>
<Text id=\"home.title\">Home</Text>
</h1>
<p>
<Text id=\"home.text\">This is the Home component.</Text>
</p>
</div>
);
export default Home;





 
 

后备文字
 

为了避免网页中出现空白,我们应该在<Text>中输入后备文字。 如果preact-i18n无法在您的definition中找到相关的文字或句子,那preact-i18n将会使用你刚才在 <Text>…</Text>输入的后备文字。
<Text id=\"unknown.definition\">This is a fallback text.</Text>


// 这将会渲染: \"This is a fallback text.\"
Localizer 和 MarkupText
如果您是想要翻译HTML属性中的文字 (比如说 placeholder=\"\"或是title=\"\"等等),您应该使用<Localizer>,而并不是使用<Text>。

相反的,如果您是想要在您的翻译的文字或句子中使用HTML Markup, 您必须使用<MarkupText>。<MarkupText>将会把已翻译好的文字或句子渲染在一个<span>tag中。

在以下的例子中,我们将会在我们的definition文件中添加多几行的代码。first_name及last_name,将会使用在<Localizer>中的例子。 而我们会在<MarkupText>中的例子使用link。
{ 
\"first_name\": \"名\",
\"last_name\": \"姓\",
\"link\": \"这是个<a href=\'https://www.google.com\'>连结</a>\"
}

在你更新主页(src/routes/home/index.js)中的内容之前,记得将Localizer和MarkupText导入到该页中:
import { Text, Localizer, MarkupText } from \'preact-i18n\';
const Home = () => (
<div>
<Localizer>
<input placeholder={<Text id=\"first_name\" />} />
</Localizer>
<Localizer>
<input placeholder={<Text id=\"last_name\" />} />
</Localizer>
<MarkupText id=\"link\">
This is a <a href=\"https://www.google.com\">link</a>
</MarkupText>
</div>
);
export default Home;





模板 (Templating)
 

如果您想要在您的definition中注入一些自定义的字符串,您可以使用fields属性来实现。

首先呢,我们需要先更新我们的definition文件。在我们的definition文件中,我们需要将我们要被自定义的字符串替代的文字,更改成像{{count}}或者是{{total}}这样子的占位符。
{
  \"page\": \"{{count}} / {{total}} 页\"
}
之后呢,我们需要在我们的<Text />中加入fields属性。因此,您的代码应如下所示:
import { Text } from \'preact-i18n\'; 
const Home = () => (
<div>
<h2>
<Text id=\"page\" fields={{ count: 5, total: 10 }}>
5 / 10 Pages
</Text>
</h2>
</div>
);
export default Home;






 
 

 
复数 (Pluralization)

如果您要翻译的语言有复数的话(比如说像英文:apple / apples),您可以使用以下其中一个方法,来把已翻译好的文字和句子放进您的definition文件里。

\"key\": { \"singular\":\"apple\", \"plural\":\"apples\" }
\"key\": { \"none\":\"no apples\", \"one\":\"apple\", \"many\":\"apples\" }
\"key\": [\"apples\", \"apple\"]
在以下的例子中,我们将会把模板和复数的例子结合在一起。但在那之前,我们需要更新我们的definition文件:
{
\"apple\": {
\"singular\": \"Henry has {{count}} apple.\",
\"plural\":\"Henry has {{count}} apples.\"
}
}


接着,我们将会把以下的代码粘贴到src/routes/home/index.js中:
import { Text } from \'preact-i18n\'; 
const Home = () => (
<div>
<p>
<Text id=\"apple\" plural={1} fields={{ count: 1 }} />
</p>
<p>
<Text id=\"apple\" plural={100} fields={{ count: 100 }} />
</p>
</div>
);
export default Home;





 

 
 根据以上的步骤,你就能在您的Preact项目中使用模板和复数。

动态导入definition文件
在现实情况中,您将会根据用户的选择来设定网页的语言。

您可以使用游览器的语言(通过navigator.language), 或者是让用户自己手动更换语言。

然而,为了避免我们将不必要的definition文件导入进去,我们可以使用import()来实现动态导入definition文件。这样一来,我们只会导入用户所选择的语言所需要的definition文件。
import { Component } from \'preact\'; 
import { IntlProvider } from \'preact-i18n\';
import defaultDefinition from \'../i18n/zh-tw.json\';
export default class App extends Component {
state = {
definition: defaultDefinition
}
changeLanguage = (lang) => {
// 我们可以使用这个函数来更换语言
import(`../i18n/${lang}.json`)
.then(definition => this.setState({ definition }));
};
render({ }, { definition }) {
return (
<IntlProvider definition={definition}>
<div id=\"app\" />
</IntlProvider>
);
}
}



根据以上的例子,我们可以使用这函数:this.changeLanguage(\"zh-TW\") 来导入definition文件并更改网页的语言。

谁在使用preact-i18n?
我自己的业余项目: Remote for Slides,正在使用着preact-i18n。

Remote for Slides是一个渐进式网络应用程序(PWA) + Chrome 扩充器。这能让用户在任何设备上,远程遥控Google简报。是时候跟昂贵的翻页笔说再见了。

Remote for Slides 渐进式网络应用程序支持多达8个语言,包括了英文、繁体中文、简体中文、加泰罗尼亚文、西班牙文、 法文、波兰文、以及Euskera。

在这个项目中,我也使用了我在刚才提到的 \"动态导入definition文件\" 的方法。这可以避免应用程序导入一些没使用到的definition文件。这将会提升应用程序性能。

除此之外,Remote for Slides 渐进式网络应用程序也将会自动地设置语言。这应用程序将会根据游览器的语言(navigator.language)、或者是根据URL中的parameter (ie: s.limhenry.xyz/?hl=zh-tw)来更改语言。 当然,用户也可以从设置中更改语言。
 

 
0
Pay Tips 06-04-20

0 comments

If you wanna get more accurate answers, Please Login or Register