2021SC@SDUSC
目录
I18nTransformer.java
1.总结
1.概述
i18n transformer通过在配置的目录中查找用户区域设置的翻译来工作。Locale作为参数传递给transformer,它可以由LocaleAction根据请求、会话或cookie数据确定。
然后,对于传递的本地消息,它尝试查找满足本地语言环境的消息目录,并使用它来处理i18n标记指示的文本替换。
消息目录保存在单独的文件中,命名约定与ResourceBundle类似。即basename_locale,其中basename可以是任何名称,locale可以是使用ISO 639/3166字符指定的任何语言环境(例如en_AU、de_AT、es)。
2.信息目录
目录的格式如下:
<?xml version="1.0"?>
<!-- message catalogue file for locale ... -->
<catalogue xml:lang="locale">
<message key="key">text <i>or</i> markup</message>
....
</catalogue>
其中key指定该语言的特定消息。
3.用法
要翻译的文件包含以下标记:
<?xml version="1.0"?>
... some text, translate <i18n:text>key</i18n:text>
在运行时,i18n transformer将查找用户区域设置的消息目录,并使用标记之间的值作为查找键,适当地替换<i18n:text>标记之间的文本。
如果i18n transformer无法为用户给定的语言环境找到合适的消息目录,它将递归地尝试查找父消息目录,直到找到有效的目录。即:
- catalogue_language_country_variant.xml
- catalogue_language_country.xml
- catalogue_language.xml
- catalogue.xml
这允许开发人员编写消息目录的层次结构,在每个层次上定义具有不断增加的变化深度的消息。
此外,目录可以跨多个位置拆分。例如,一个目录中可能有一个默认目录,而另一个目录中有一个用户或客户机特定目录。目录将按照指定的位置顺序进行搜索,但仍遵循上述指定的区域设置顺序。例如:假设消息的基本名称和en_AU(无变体)的区域设置以及翻译/客户端和翻译的位置,将进行以下搜索:
翻译/client/messages_en_AU.xml
翻译/消息_en_.xml
翻译/client/messages_en.xml
翻译/messages\u entransations/client/messages.xml
translations/messages.xml
i18n:text元素可以选择使用属性i18n:catalog来指示要使用的特定目录。此属性的值应该是要使用的目录的id(请参见站点地图配置)。
4.站点地图配置
<map:transformer name="i18n"
src="org.apache.cocoon.transformation.I18nTransformer">
<catalogues default="someId">
<catalogue id="someId" name="messages" [location="translations"]>
[<location>translations/client</location>]
[<location>translations</location>]
</catalogue>
...
</catalogues>
<untranslated-text>untranslated</untranslated-text>
<preload>en_US</preload>
<preload catalogue="someId">fr_CA</preload>
</map:transformer>
目录:定义目录的容器元素。它必须有一个属性“default”,其值是目录元素的id之一。(强制性)。
目录:指定目录。它需要两个必需的属性:id(可以是您喜欢的任何一个)和name(目录的基本名称)。位置(邮件目录的位置)也是必需的,但可以指定为属性或一个或多个子元素,但不能同时指定两者。如果指定了多个位置,则目录将按照它们在配置中出现的顺序进行搜索。名称和位置可以包含对InputModule的引用(与站点地图中其他位置的语法相同)。它们在变压器的每次使用中都会得到解决,因此它们可以参考例如请求参数。(至少需要一个目录元素)。解析输入模块引用后,位置字符串可以是URI的根。例如,使用消息名称和en_GB语言环境指定cocoon:/test的位置将导致站点地图尝试处理cocoon:/test/messages\u en_GB.xml、cocoon:/test/messages\u en.xml和cocoon:/test/messages.xml。
未翻译文本:用于未翻译键的文本(默认为输出键名)。
预加载:要预加载的目录的区域设置。将尝试解析指定区域设置的所有配置目录。如果存在可选目录属性,将仅预加载指定目录。可以指定多个预加载元素。
5.管道使用
要在管道中使用转换器,只需在特定转换中指定它,然后传递locale参数:
<map:match pattern="file">
<map:generate src="file.xml"/>
<map:transform type="i18n">
<map:parameter name="locale" value="..."/>
</map:transform>
<map:serialize/>
</map:match>
您可以使用LocaleAction或任何其他方式为transformer提供区域设置。
如果在某些管道中,希望使用不同的目录作为默认目录,可以通过指定名为default-catalog-id的参数来实现。
通过将未翻译文本指定为参数,还可以在管道级别覆盖该文本。
6.i18n标记
- <i18n:date/>提供本地化日期。
- <i18n:date-time/>提供本地化的日期和时间。
- <i18n:time/> 给出本地时间。
- <i18n:number/> 给出了本地化的数字。
- <i18n:currency/>提供本地化货币。
- <i18n:percent/> 给出本地化的百分比。
2.属性
static String CURRENCY_LOCALE_ATTRIBUTE
// 此属性用于指定不同的语言环境。
protected BundleFactory factory
// 消息包加载器工厂组件(服务)
static String I18N_ATTR_ATTRIBUTE
// 此属性与任何元素(甚至不是 i18n)一起使用以转换属性值。
static String I18N_CATALOGUE_ATTRIBUTE
// 此属性可用于i18n:text指示应从中检索密钥的目录。
static String I18N_CHOOSE_ELEMENT
// i18n:choose element 用于就地转换元素。
static String I18N_CURRENCY_ELEMENT
// 货币要素名称
static String I18N_CURRENCY_NO_UNIT_ELEMENT
// 没有单位元素名称的货币
static String I18N_DATE_ELEMENT
// i18n:date 用于提供本地化的日期字符串。
static String I18N_DATE_TIME_ELEMENT
// i18n:date-time 用于提供本地化的日期和时间字符串。
static String I18N_DEFAULT_CATALOGUE_ID
// 此配置参数指定要用作默认目录的目录的 id,允许在管道级别重新定义默认目录。
static String I18N_EXPR_ATTRIBUTE
// 此属性与任何元素(甚至不是 i18n)一起使用来评估属性值。
static String I18N_FRACTION_DIGITS_ATTRIBUTE
// fraction-digits属性用于 i18:number指示分数后面的位数
static String I18N_IF_ELEMENT
// i18n:if 用于测试语言环境。
static String I18N_INT_CURRENCY_ELEMENT
// 整数货币元素名称
static String I18N_INT_CURRENCY_NO_UNIT_ELEMENT
// 没有单位元素名称的整数货币
// 该属性与i18n:text元素一起用于指示相应消息的键。如果此键未找到任何消息,则将使用
//元素的字符数据。
static String I18N_KEY_ATTRIBUTE
// 此属性与 i18n:text 元素一起使用以指示相应消息的键。
static String I18N_LOCALE
// 此配置参数指定要使用的默认语言环境。
static String I18N_LOCALE_ATTRIBUTE
// 此属性与日期和数字格式化元素一起使用,以指示应该用于格式化元素值的区域设置。
static String I18N_NAMESPACE_URI
// i18n 的命名空间是“http://apache.org/cocoon/i18n/2.1”。
static String I18N_NUMBER_ELEMENT
// i18n:number 用于提供本地化的数字字符串。
static String I18N_OLD_NAMESPACE_URI
// i18n 的旧命名空间是“http://apache.org/cocoon/i18n/2.0”。
static String I18N_OTHERWISE_ELEMENT
// i18n:otherwise当在i18n:choose 块内找不到匹配的语言环境时,用于匹配任何语言环境。
static String I18N_PARAM_ELEMENT
// i18n:param 与 i18n:translate 一起使用以提供替换参数。
static String I18N_PARAM_NAME_ATTRIBUTE
// 此属性会影响可用于替换的参数名称。
static String I18N_PATTERN_ATTRIBUTE
// 此属性与日期和数字格式元素一起使用,以指示应用于设置元素值格式的模式。
static String I18N_PERCENT_ELEMENT
// 百分比元素名称
static String I18N_PRELOAD
// 此配置参数指定应为其预加载目录的语言环境。
static String I18N_SRC_LOCALE_ATTRIBUTE
// 此属性与日期和数字格式元素一起使用,以指示应用于解析元素值的区域设置。
static String I18N_SRC_PATTERN_ATTRIBUTE
// 此属性与日期和数字格式元素一起使用,以指示应该用于解析元素值的模式。
static String I18N_TEXT_ELEMENT
// i18n:text element 用于翻译任何带有或不带有标记的文本。
static String I18N_TIME_ELEMENT
// i18n:time 用于提供本地化的时间字符串。
static String I18N_TRANSLATE_ELEMENT
// i18n:translate element 用于翻译带有参数替换的文本。
static String I18N_UNTRANSLATED
// 此配置参数指定在未翻译文本(未找到消息)的情况下应显示的消息。
static String I18N_VALUE_ATTRIBUTE
// 此属性与日期和数字格式化元素一起使用,以指示应解析和格式化的值。
static String I18N_WHEN_ELEMENT
// i18n:when 用于测试语言环境。
protected Locale locale
// 当地的
protected ServiceManager manager
// 组件(服务)经理
protected Map objectModel
3.方法
private Attributes translateAttributes(final String element, Attributes attr)
throws SAXException {
if (attr == null) {
return null;
}
AttributesImpl tempAttr = null;
//将i18n:attr=“name1 name2…”中的所有属性的值作为键进行转换。
int attrIndex = attr.getIndex(I18N_NAMESPACE_URI, I18N_ATTR_ATTRIBUTE);
if (attrIndex == -1) {
// 尝试旧名称空间
attrIndex = attr.getIndex(I18N_OLD_NAMESPACE_URI, I18N_ATTR_ATTRIBUTE);
}
if (attrIndex != -1) {
StringTokenizer st = new StringTokenizer(attr.getValue(attrIndex));
//制作一份我们将要修改的副本
tempAttr = new AttributesImpl(attr);
// 删除I18n:AtTo属性,我们不再需要它了
tempAttr.removeAttribute(attrIndex);
// 遍历列出的属性并转换它们
while (st.hasMoreElements()) {
final String name = st.nextToken();
int index = tempAttr.getIndex(name);
if (index == -1) {
getLogger().warn("Attribute " +
name + " not found in element <" + element + ">");
continue;
}
String value = translateAttribute(element, name, tempAttr.getValue(index));
if (value != null) {
// 设置转换值。如果为null,则不执行任何操作。
tempAttr.setValue(index, value);
}
}
attr = tempAttr;
}
// 将i18n:expr=“name1 name2…”中的所有属性的值作为键进行转换。
attrIndex = attr.getIndex(I18N_NAMESPACE_URI, I18N_EXPR_ATTRIBUTE);
if (attrIndex != -1) {
StringTokenizer st = new StringTokenizer(attr.getValue(attrIndex));
if (tempAttr == null) {
tempAttr = new AttributesImpl(attr);
}
tempAttr.removeAttribute(attrIndex);
// 遍历列出的属性并对其求值
while (st.hasMoreElements()) {
final String name = st.nextToken();
int index = tempAttr.getIndex(name);
if (index == -1) {
getLogger().warn("Attribute " +
name + " not found in element <" + element + ">");
continue;
}
final StringBuffer translated = new StringBuffer();
// 计算{..}表达式
VariableExpressionTokenizer.TokenReciever tr = new VariableExpressionTokenizer.TokenReciever () {
private String catalogueName;
public void addToken(int type, String value) {
if (type == MODULE) {
this.catalogueName = value;
} else if (type == VARIABLE) {
translated.append(translateAttribute(element, name, value));
} else if (type == TEXT) {
if (this.catalogueName != null) {
translated.append(translateAttribute(element,
name,
this.catalogueName + ":" + value));
this.catalogueName = null;
} else if (value != null) {
translated.append(value);
}
}
}
};
try {
VariableExpressionTokenizer.tokenize(tempAttr.getValue(index), tr);
} catch (PatternException e) {
throw new SAXException(e);
}
// 设置转换值。
tempAttr.setValue(index, translated.toString());
}
attr = tempAttr;
}
// 无需翻译,只需返回即可
return attr;
}
void characters(char[] ch, int start, int len)
void configure(Configuration conf)
// 可配置接口的实现。
void dispose()
void endElement(String uri, String name, String raw)
Serializable getKey()
// CacheableProcessingComponents 的实现。
Locale getLocale()
// 返回此转换器实例的当前语言环境设置。
protected ParamSaxBuffer getMessage(String catalogueID, String key)
// 从字典中检索消息的辅助方法。
SourceValidity getValidity()
// CacheableProcessingComponent 的实现。
void recycle()
void service(ServiceManager manager)
// 查找BundleFactory要使用的。
void setup(org.apache.cocoon.environment.SourceResolver resolver, Map objectModel, String source, Parameters parameters)
// 设置变压器的当前实例。
void startElement(String uri, String name, String raw, Attributes attr)