# 国际化语言
>[info] 核心版本`1.7.0`增加
> 从核心`1.7.0`开始,框架内引入了国际化概念。
假如你在核心`1.7.0`更新后翻翻源代码,你会发现源代码中的resources中或者根路径中多了这么一个文件夹:`lang`,其下也有一些文件格式为`lang`的文件。这些就是语言文件。
## **语言文件**
### **格式与命名**
语言文件是一种扩展名为`lang`、格式与`properties`文件相同的文件。这些文件的命名规则为`${语言地区}.lang`,举个例子,代表了英文语言的语言文件名称为`en_US.lang`,而代表了中文语言文件的文件名为`zh_CN.lang`。
以下为一个英文语言文件`en_US.lang`的示例:
```properties
lang.init.finished=language has already init finished. All non-Chinese languages are from Google Translate.
# system type
run.os.name=System name: {0}
run.os.version=System version: {0}
```
以下为一个对应的中文语言文件`zh_CN.lang`的示例:
```properties
lang.init.finished=语言已初始化完毕。
# 启动时候的系统类型展示
run.os.name=系统名称: {0}
run.os.version=系统版本: {0}
```
### **语言地区定义**
那么问题来了,我要怎么才能知道一个语言的`语言地区`是怎样的呢?
你可以去了解一下Java的`Locale`国际化类,此功能就是基于`Locale`来实现的。
>[success] 比较常用的就是英文`en_US`和中国大陆简体中文`zh_CN`了。
### **Tag标签与格式**
Tag标签指的就是properties键值对中的`键`,也就是等号左边的字符串。它们的格式与`包路径`很像。
从上面的示例可以看到,有些语言信息出现了`{0}`的字样,这是Java中`MessageFormat`信息格式化的参数占位符。使用大括号与索引组成,例如 `系统版本: {0}` 或者 `结果为:{0} 或 {1}`
使用占位符后,最终格式化后的结果就是你所填入的字符串参数,且根据索引顺位。
字符串的消息的转义字符是单引号`'`而不是反斜杠`\`。
>[success] 具体且详细的格式化规则可以去了解下`MessageFormat`
### **文件结构**
语言文件的加载是自动化的(当然也可以手动触发,后续会讲到),那么文件的存放格式就需要有一定的规则。
目录结构如下(项目的资源路径`resources`):
```
- lang
├ core
└ core_lang1.lang
└ core_lang2.lang
├ component
└ component_lang1.lang
└ component_lang2.lang
├ user_lang1.lang
└ user_lang2.lang
```
如上示例,`resources`资源路径下的`lang`文件夹下有两个子文件夹和一些`lang`文件。
- **`lang/core/`**
`lang/core/`路径下的语言文件是核心所使用的语言文件。
- **`lang/component/`**
`lang/component/`路径下的语言文件是组件自己实现并使用的语言文件。
- **`lang/`**
`lang/`文件夹根目录下的`lang`文件是一些用户自定义的**可能存在的**`lang`文件。
### **自定义与覆盖**
如果用户想要自定义一些自己的语言文件,可以根据语言区域命名好后放在`lang/`路径的根路径下。
如果用户想要修改原有的一些语言文件,则根据上述文件结构进行覆盖即可。
>[warning] 在自定义或者覆盖的时候,请至少保证存在`en_US.lang`,即英文语言文件。英文语言会作为默认语言与备用语言,永远会首先被尝试加载。
## **语言类与使用**
### **加载与初始化**
语言类定义为`com.forte.lang.Language`
语言的加载会在启动的时候自动初始化。如果你想要在其他地方手动初始化,你可以使用`init`方法:
```java
Language.init();
```
>[success] `init`方法存在多个重载,一般都是用于指定加载的语言与所使用的类加载器。如果无参数,则使用默认类加载器与当前系统语言。
语言的加载顺序如下:
1. 加载`lang/core/`路径下对应的英文语言与当前系统语言。
2. 加载`lang/component/`路径下的对应英文语言与当前系统语言。
3. 如果有,加载`lang/`路径下的对应英文语言与当前系统语言的用户自定义语言。
>[info] 由上可见,无论如何都会加载一个英文语言作为默认语言,所以你应当首先保证英文语言信息的完整性。
### **使用**
>[info] 对于语言系统的使用,有一部分特殊的类或者环境有特殊的规则,这里将特殊的规则留在此章节的子章节中,此处不做介绍。
首先,此处展示用作示例的语言文件内容:
```properties
lang.test=测试信息
test.user.name=姓名为 {0}
test.user.age=年龄为 {0}
```
>[success] 以下代码均假设语言已经初始化完毕。
- 1- **Language.format**
`Language`提供了几种`format`方法来获取格式化后的信息字符串。
```java
System.out.println( Language.format("lang.test") );
System.out.println( Language.format("test.user.name", new Object[]{"张三"}));
System.out.println( Language.format("test.user.age", 18));
System.out.println( Language.format("aaa.bbb.ccc.ddd"));
```
输出结果:
```
测试信息
姓名为 张三
年龄为 18
aaa.bbb.ccc.ddd
```
>[warning] 可以看到,不存在的`Tag`会被原样返回。
>[warning] 其中,`test.user.name`的参数`张三`之所以写成`new Object[]`的格式是因为`format`方法存在一个前两个参数都是字符串的重载方法,此处防止参数混淆。
- 2 - **QQLog**
QQLog已经整合了Language,在使用`info`、`debug`等输出日志方法的时候会自动尝试通过Tag与参数进行格式化。
```java
QQLog.info("lang.test");
QQLog.info("test.user.name", "张三");
QQLog.info("test.user.age", 18);
QQLog.info("aaa.bbb.ccc.ddd");
```
输出结果:
```
[2020-02-26T21:00:00.479] [INFO] 测试信息
[2020-02-26T21:00:00.483] [INFO] 姓名为 张三
[2020-02-26T21:00:00.490] [INFO] 年龄为 18
[2020-02-26T21:00:00.490] [INFO] aaa.bbb.ccc.ddd
```
可以看到,QQLog可以直接使用`Tag`进行输出。
- 前言
- 简单介绍
- 我该如何阅读文档
- 视频教程
- 安装与使用
- 开源协议
- 免责&捐助
- 注意事项
- 版本命名规则简介
- 主要功能版本历史
- 功能指引
- 通用API与功能
- 国际化语言
- 异常
- 消息监听
- @Listen
- @OnListen模板
- @Filter
- 消息参数截取
- @Spare
- @Constr
- @Ignore
- @ListenBreak
- @ListenBreakPlugin
- @ListenBody
- 监听响应
- 成功判定与返回值
- 监听上下文
- 动态参数
- 监听消息API
- 异步监听 @Async
- 限流监听 @Limit
- 自定义Http送信器
- 枚举与类型
- 送信器
- SENDER
- SETTER
- GETTER
- 返回值
- 其他位置
- 日志与日志拦截
- 异常处理
- 依赖注入
- 自定义依赖获取
- 批量依赖载入
- 注意事项
- 常量
- 定时任务
- 自定义过滤
- 拦截器
- 拦截器总定义
- 上下文对象总定义
- 监听消息拦截
- 送信器拦截
- 监听函数拦截
- CAT码
- CQ码
- CQCode
- CQ码工具类
- CQ扩展工具类
- AppendList拼接链
- 高级内容
- 阻断机制
- 截断机制
- 自定义枚举类型
- 枚举工厂
- byName注解
- 自定义注解
- 配置
- 文件配置
- 注解配置
- 参数配置
- 多配置
- 多账号
- 自定义账号管理器
- 小心!
- 核心版本与组件如何升级核心
- 核心版本迭代指南
- 核心
- 更新日志
- jar包与依赖
- 监听消息类结构图
- 快速启动
- 模组与扩展
- 模组开发
- 现有模组
- 通用模组-延时任务
- 通用模组-CQ码工具
- 转义器
- CQ码操作工具类
- CQ码模板-CodeTemplate
- CQ码载体-KQCode
- CQ码构建器
- MQ码工具类
- 通用模组-redis-bot管理器
- 通用模组-Debugger
- Debugger-common模块
- Debugger-server模块
- Debugger-client模块
- 通用模组-钉钉机器人
- 组件-Mirai(JVM)
- 快速开始(1.13+)
- springboot-starter
- 注意事项
- 配置
- 额外的内容
- 快速回复
- 额外监听
- CQ码解析
- 组件-酷Q(QQ)-CQ HTTP API(基本失效)
- 快速开始(推荐)
- 快速开始(1.7.x以下,不推荐)
- 快速开始(Springboot启动器)
- 启动器、启动接口与配置类
- 配置
- 文件配置
- 注意事项
- 更新日志
- 额外的内容
- 自定义额外监听
- CQ送信器
- 元事件
- 监听消息类结构图
- 组件-酷Q(QQ)-JCQ(失效)
- 快速开始
- 更新日志
- 额外的内容
- JCQ日志
- 配置
- 注意事项
- 监听消息类结构图
- 组件-酷Q(QQ)-HTTP TO CQ(失效)
- 快速开始(核心1.7.x及以下)
- 启动器、启动接口与配置类
- 配置
- 文件配置
- 注意事项
- 更新日志
- 监听消息类结构图
- 组件-酷Q(QQ)-LEMOC (失效)
- 快速开始(核心1.7.x及以下)
- 配置
- 注意事项
- 更新日志
- 监听消息类结构图
- Springboot快速启动器
- 常见问题汇总
- BUG反馈
- 更新计划总览