国际化是一个设计过程,旨在确保产品(网站或应用)能够适应各种语言和地区,而无需对源代码进行工程更改。将国际化视为本地化的准备。
¥Internationalization is a design process that ensures a product (a website or application) can be adapted to various languages and regions without requiring engineering changes to the source code. Think of internationalization as readiness for localization.
提示
处理网站/应用的推荐软件包是 vue-i18n。此包应通过 @quasar/app-vite Boot File 或 @quasar/app-webpack Boot File 添加。在启动文件文档页面,你可以看到一个插入 vue-i18n 的具体示例。
¥The recommended package for handling website/app is vue-i18n. This package should be added through a @quasar/app-vite Boot File or a @quasar/app-webpack Boot File. On the Boot File documentation page you can see a specific example for plugging in vue-i18n.
警告
Quasar 文档假设你已经熟悉 vue-i18n。下面仅描述了如何在 Quasar CLI 项目中使用它的基本方法。有关其功能的完整列表,请访问 Vue 国际化文档。
¥Quasar documentation assumes you are already familiar with vue-i18n. Below it’s described only the basics of how to make use of it in a Quasar CLI project. For the full list of its features please visit the Vue I18n documentation.
手动设置(Setup manually)
¥Setup manually
如果你在 yarn create quasar
(或 npm init quasar@latest
,或 pnpm 或 Bun 等效程序)向导中没有启用 i18n,你可以按照以下步骤手动设置。
¥If you missed enabling i18n during yarn create quasar
(or npm init quasar@latest
or the pnpm or Bun equivalent) wizard, here is how you can set it up manually.
将
vue-i18n
依赖安装到你的应用中。¥Install the
vue-i18n
dependency into your app.
$ yarn add vue-i18n
创建一个包含以下内容的
src/boot/i18n.js
文件:¥Create a file
src/boot/i18n.js
with following content:
import { defineBoot } from '#q-app/wrappers'
import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'
export default defineBoot(({ app }) => {
const i18n = createI18n({
locale: 'en-US',
globalInjection: true,
messages
})
// Set i18n instance on app
app.use(i18n)
})
在应用中创建一个文件夹 (/src/i18n/),用于保存你将支持的每种语言的定义。示例:src/i18n。请注意步骤 2 中的 “import messages from ‘src/i18n’”。这是你编写要导入内容的步骤。
¥Create a folder (/src/i18n/) in your app which will hold the definitions for each language that you’ll support. Example: src/i18n. Notice the “import messages from ‘src/i18n’” from step 2. This is step where you write the content that gets imported.
现在在
boot
部分的quasar.config
文件中引用此文件:¥Now reference this file in
quasar.config
one in theboot
section:
return {
boot: [
// ...
'i18n'
],
// ...
}
现在你可以在页面中使用它了。
¥Now you are ready to use it in your pages.
在你的单函数 (SFC) 中设置翻译块 @quasar/app-vite only(Setting up Translation Blocks in your SFCs @quasar/app-vite only)
¥Setting up Translation Blocks in your SFCs
警告
以下部分仅适用于使用 @quasar/app-vite 的项目!
¥The following section applies to projects that use @quasar/app-vite only!
如果我们想在 Quasar CLI 项目的 SFC(单文件组件)中添加对 <i18n>
标签的支持,则需要修改现有配置。
¥If we want to add support to the <i18n>
tag inside a SFC (single file component) in a Quasar CLI project then we need to modify the existing configuration.
我们首先安装 @intlify/unplugin-vue-i18n
包:
¥We first install the @intlify/unplugin-vue-i18n
package:
$ yarn add --dev @intlify/unplugin-vue-i18n
然后我们编辑 /quasar.config 文件:
¥Then we edit the /quasar.config file:
import { fileURLToPath } from 'node:url'
// ...
build: {
vitePlugins: [
['@intlify/unplugin-vue-i18n/vite', {
// if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
// compositionOnly: false,
// if you want to use named tokens in your Vue I18n messages, such as 'Hello {name}',
// you need to set `runtimeOnly: false`
// runtimeOnly: false,
ssr: ctx.modeName === 'ssr',
// you need to set i18n resource including paths !
include: [ fileURLToPath(new URL('./src/i18n', import.meta.url)) ]
}]
]
}
如何使用(How to use)
¥How to use
以下是显示主要用例的示例:
¥Here is an example displaying the main use cases:
<template>
<q-page>
<!-- text interpolation, reactive -->
{{ $t('hello') }}
<!-- prop/attr binding, reactive -->
<q-btn :label="$t('hello')" />
<!-- v-html directive usage -->
<span v-html="content"></span>
</q-page>
</template>
<script setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
// bound to a static variable, non-reactive
// const staticContent = t('hello')
// bound to a reactive variable, but one-time assignment, locale changes will not update the value
// const reactiveStaticContent = ref(t('hello'))
// bound to a reactive variable, locale changes will reflect the value
const content = computed(() => t('hello'))
function notify() {
Notify.create({
type: 'positive',
message: t('hello')
})
}
</script>
添加新语言(Add new language)
¥Add new language
假设你要添加新的德语语言。
¥Let’s say you want to add new German language.
创建新文件
src/i18n/de/index.js
,并将文件src/i18n/en-US/index.js
的内容复制到该文件,然后更改语言字符串。¥Create the new file
src/i18n/de/index.js
and copy there the content of the filesrc/i18n/en-US/index.js
then make changes to the language strings.现在更改
src/i18n/index.js
并在那里添加新的de
语言。¥Now change
src/i18n/index.js
and add the newde
language there.
import enUS from './en-US'
import de from './de'
export default {
'en-US': enUS,
'de': de
}
创建语言切换器(Create language switcher)
¥Create language switcher
<template>
<!-- ...... -->
<q-select
v-model="locale"
:options="localeOptions"
label="Quasar Language"
dense
borderless
emit-value
map-options
options-dense
style="min-width: 150px"
/>
<!-- ...... -->
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { locale } = useI18n({ useScope: 'global' })
const localeOptions: [
{ value: 'en-US', label: 'English' },
{ value: 'de', label: 'German' }
]
</script>
UPPERCASE(UPPERCASE)
许多语言,例如希腊语、德语和荷兰语,对于大写字母的显示规则并不直观,并且你应该注意以下一种特殊情况:
¥Many languages, such as Greek, German and Dutch have non-intuitive rules for uppercase display, and there is an edge case that you should be aware of:
QBtn 组件将使用 CSS text-transform: uppercase
规则自动将其标签转换为全大写。根据 MDN 网页文档、“语言由 HTML 属性 lang 或 XML 属性 xml:lang 定义。” 规范,遗憾的是,这在各个浏览器中的实现并不完善,而且 2017 年 ISO 标准中关于大写德语 eszett ß
的规范尚未真正成为规范。目前你有两个选择:
¥QBtn component will use the CSS text-transform: uppercase
rule to automatically turn its label into all-caps. According to the MDN webdocs, “The language is defined by the lang HTML attribute or the xml:lang XML attribute.” Unfortunately, this has spotty implementation across browsers, and the 2017 ISO standard for the uppercase German eszett ß
has not really entered the canon. At the moment you have two options:
在标签中使用
no-caps
属性,并按应有的方式编写字符串。¥use the prop
no-caps
in your label and write the string as it should appear在标签中使用属性
no-caps
,并使用$q.lang.getLocale()
检测到的语言环境将字符串重写为 toLocaleUpperCase¥use the prop
no-caps
in your label and rewrite the string with toLocaleUpperCase by using the locale as detected by$q.lang.getLocale()
检测语言环境(Detecting Locale)
¥Detecting Locale
Quasar 还提供了一种开箱即用的方法来确定用户语言环境:
¥There’s also a method to determine user locale which is supplied by Quasar out of the box:
// outside of a Vue file
import { Lang } from 'quasar'
Lang.getLocale() // returns a string
// inside of a Vue file
import { useQuasar } from 'quasar'
setup () {
const $q = useQuasar()
$q.lang.getLocale() // returns a string
}
警告
如果你使用 Quasar 的 set 方法($q.lang.set()
),这将不会反映在上面 Quasar 的 getLocale 中。这样做的原因是,getLocale()
始终会返回用户的区域设置(基于浏览器设置)。set()
方法引用 Quasar 的内部语言环境设置,用于确定要使用的语言文件。如果你想查看使用 set()
设置了哪种语言,你可以使用 $q.lang.isoName
。
¥If you use Quasar’s set method ($q.lang.set()
), this will not be reflected by Quasar’s getLocale above. The reason for this is that getLocale()
will always return the users locale (based on browser settings). The set()
method refers to Quasars internal locale setting which is used to determine which language file to use. If you would like to see which language has been set using set()
you can use $q.lang.isoName
.