如何在 Grails 应用中更改语言?
了解如何更改应用程序中使用的默认语言、在不同语言之间切换或访问当前地区设置。
作者:Sergio del Amo
Grails 版本 3.3.11
1 Grails 培训
Grails 培训 - 由创建和积极维护 Grails 框架的人员开发和交付!。
2 入门
在此指南中,你将学习如何创建一个界面翻译成四种语言的应用。
你将学习如何在应用程序中更改使用的默认语言以及如何在使用应用程序时在不同语言之间切换。
2.1 你需要什么
要完成此指南,你需要以下内容
-
一些时间
-
优秀的文本编辑器或 IDE
-
安装 JDK 1.7 或更高版本,并正确配置
JAVA_HOME
2.2 如何完成指南
请执行以下操作以开始
-
下载并解压缩源代码
或
-
克隆 Git 存储库
git clone https://github.com/grails-guides/grails_i18n.git
Grails 指南存储库包含两个文件夹
-
initial
初始项目。通常是一个简单的 Grails 应用,其中包含一些附加代码,以便让你开个头。 -
complete
完成的示例。它遵循指南提供的步骤进行操作,并将这些更改应用到initial
文件夹的结果。
要完成指南,请转到 initial
文件夹
-
cd
进入grails-guides/grails_i18n/initial
并按照下一节中的说明进行操作。
如果您cd 到grails-guides/grails_i18n/complete ,您可以直接前往完成的示例 |
3 编写应用程序
Grails 开箱即支持国际化 (i18n),这是通过利用 Spring MVC 的基础国际化支持实现的。使用 Grails,您可以根据用户的语言环境自定义视图中显示的文本
3.1 消息包
Grails 中的消息包位于grails-app/i18n
目录中,且是简单的 Java 属性文件。
我们希望在我们的应用程序中支持英语、西班牙语、意大利语和德语。我们将在不同的消息包中定义本地化。
默认消息包
navbar.applicationStatus=Application Status
navbar.artefacts=Artefacts
navbar.installedPlugins=Installed Plugins
navbar.languages=Languages
language.en=English
language.es=Spanish
language.de=German
language.it=Italian
welcome.title=Welcome to Grails
welcome.body=Congratulations, you have successfully started your first Grails application! At the moment this is the default page, feel free to modify it to either redirect to a controller or display whatever content you may choose. Below is a list of controllers that are currently deployed in this application, click on each to execute its default action:
西班牙语消息包
navbar.applicationStatus=Estado de la aplicación
navbar.artefacts=Artefactos
navbar.installedPlugins=Plugins instalados
navbar.languages=Idiomas
language.en=Inglés
language.es=Español
language.de=Alemán
language.it=Italiano
welcome.title=Bienvenido a Grails
welcome.body=¡Enhorabuena, ha iniciado con éxito su primera aplicación de Grails! En este momento es la página predeterminada, no dude en modificarla para redirigir a un controlador o mostrar el contenido que elija. A continuación se muestra una lista de controladores que se implementan actualmente en esta aplicación, haga clic en cada uno para ejecutar su acción predeterminada:
意大利语消息包
navbar.applicationStatus=Stato dell'applicazione
navbar.artefacts=Artefatti
navbar.installedPlugins=Plugin installati
navbar.languages=Le lingue
language.en=Inglese
language.es=Spagnolo
language.de=Tedesco
language.it=Italiano
welcome.title=Benvenuti a Grails
welcome.body=Congratulazioni, hai iniziato con successo la tua prima applicazione Grails! Al momento questa è la pagina predefinita, sentitevi liberi di modificarla per reindirizzare a un controller o visualizzare qualsiasi contenuto che puoi scegliere. Di seguito è riportato un elenco di controller attualmente implementati in questa applicazione, fare clic su ciascuno per eseguire l'azione predefinita:
德语消息包
navbar.applicationStatus=Bewerbungsstatus
navbar.artefacts=Artefakte
navbar.installedPlugins=Installierte Plugins
navbar.languages=Sprachen
language.en=Englisch
language.es=Spanisch
language.de=Deutsche
language.it=Italienisch
welcome.title=Willkommen in Grails
welcome.body=Herzlichen Glückwunsch, Sie haben Ihre erste Grails-Anwendung erfolgreich begonnen! Im Moment ist dies die Standard-Seite, fühlen Sie sich frei, es zu ändern, um entweder auf einen Controller umzuleiten oder anzuzeigen, welche Inhalte Sie wählen können. Unten ist eine Liste von Controllern, die derzeit in dieser Anwendung bereitgestellt werden, klicken Sie auf jeden, um seine Standardaktion auszuführen:
我们在主页中使用以下消息代码
<h1><g:message code="welcome.title" /></h1>
<p><g:message code="welcome.body" /></p>
3.2 更改语言环境
您可以通过简单地将名为lang
的参数作为请求参数传递给 Grails,来切换语言环境
/?lang=es
Grails 会自动切换用户的语言环境并将其存储在 cookie 中,因此后续请求将具有新的标头。
我们通过功能测试来验证此行为
package demo
import geb.spock.GebSpec
import grails.testing.mixin.integration.Integration
@Integration
class ChangeLocaleSpec extends GebSpec {
def "change locale"() {
when:
go '/?lang=en'
then:
$('h1').text() == 'Welcome to Grails'
when:
go '/?lang=es'
then:
$('h1').text() == 'Bienvenido a Grails'
}
}
3.3 更改默认语言环境
我们希望我们的应用程序启动时默认使用西班牙语
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
// Place your Spring DSL code here
beans = {
localeResolver(SessionLocaleResolver) {
defaultLocale= new java.util.Locale('es');
}
}
我们通过功能测试来核实默认语言环境是否为西班牙语
package demo
import geb.spock.GebSpec
import grails.testing.mixin.integration.Integration
@Integration
class DefaultLocaleSpec extends GebSpec {
def "change locale"() {
when:
go '/'
then:
$('h1').text() == 'Bienvenido a Grails'
}
}
3.4 语言环境导航栏
我们在配置属性中定义受支持的语言
---
guide:
languages:
- en
- es
- it
- de
---
我们将使用标记库来呈现语言下拉列表
package demo
import grails.config.Config
import grails.core.support.GrailsConfigurationAware
import org.springframework.context.MessageSource
import org.springframework.web.servlet.support.RequestContextUtils
class LocaleNavbarTagLib implements GrailsConfigurationAware {
static namespace = 'navBar'
static defaultEncodeAs = [taglib: 'none']
MessageSource messageSource
List<String> languages
@Override
void setConfiguration(Config co) {
languages = co.getProperty('guide.languages', List) (1)
}
def localeDropdownListItems = { args ->
String uri = args.uri
for ( String lang : languages ) {
String languageCode = "language.$lang"
def locale = RequestContextUtils.getLocale(request) (2)
def msg = messageSource.getMessage(languageCode, [] as Object[], null, locale) (3)
out << "<li><a href='${uri}?lang=${lang}'>${msg}</a></li>"
}
}
}
1 | 检索配置属性 |
2 | 访问当前语言环境 |
3 | 检索本地化消息 |
我们可以使用单元测试来测试标记库呈现。
package demo
import grails.testing.web.taglib.TagLibUnitTest
import org.springframework.context.MessageSource
import spock.lang.Specification
class LocaleNavbarTagLibSpec extends Specification implements TagLibUnitTest<LocaleNavbarTagLib> {
void "LocaleNavbarTagLib method localeDropdown renders"() {
given:
def uri = '/books'
def languages = [[code: 'en', msg: 'English'],
[code: 'es', msg: 'Spanish'],
[code: 'it', msg: 'Italian'],
[code: 'de', msg: 'German']]
when:
def expected = ''
languages.each { Map m ->
expected += "<li><a href='${uri}?lang=${m.code}'>${m.msg}</a></li>"
}
tagLib.languages = languages.collect { it.code }
tagLib.messageSource = Stub(MessageSource) {
getMessage('language.en', [] as Object[], null, _) >> languages.find { it.code == 'en'}.msg
getMessage('language.es', [] as Object[], null, _) >> languages.find { it.code == 'es'}.msg
getMessage('language.it', [] as Object[], null, _) >> languages.find { it.code == 'it'}.msg
getMessage('language.de', [] as Object[], null, _) >> languages.find { it.code == 'de'}.msg
}
def result = applyTemplate('<navBar:localeDropdownListItems uri="/books"/>')
then:
cleanUpString(result) == cleanUpString(expected)
}
String cleanUpString(String str) {
str.replaceAll('\n','').replaceAll(' ', '')
}
}
我们在默认 GSP 的<content>
元素中调用标记库
。
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><g:message code="languages" default="Languages"/> <span class="caret"></span></a>
<ul class="dropdown-menu">
<navBar:localeDropdownListItems uri="${request.forwardURI}"/>
</ul>
</li>
我们向标记库提供request.forwardURI
forwardURI - 有助于获取当前请求 URI,因为请求对象的 requetURI 属性返回原始 URI,并非匹配的 URI。
4 运行应用程序
运行测试
./grailsw
grails> test-app
grails> open test-report
或
./gradlew check
open build/reports/tests/index.html
要运行应用程序,请使用 ./gradlew bootRun
命令,该命令将在端口 8080 上启动应用程序。