6.4 国际化之多语言

多语言是国际化中大家最常面对的问题,我们需要对应用的页面结构元素进行翻译,也需要对系统内容进行翻译比如:菜单、数据字典等,甚至还会业务数据进行翻译。但不管什么翻译需求,我们在实现上基本可以归类为前端翻译和后端翻译。前端翻译顾名思义是在前端根据用户选择语言对内容进行翻译,反之就是后端翻译。本文会带着大家了解oinone的前端翻译与后端翻译

准备工作

pamirs-demo-boot的pom文件中引入pamirs-translate包依赖

<dependency>
    <groupId>pro.shushi.pamirs.core</groupId>
    <artifactId>pamirs-translate</artifactId>
</dependency>

pamirs-demo-boot的application-dev.yml文件中增加配置pamirs.boot.modules增加translate,即在启动模块中增加translate模块

pamirs:
    boot:
    modules:
        - translate

后端翻译(使用)

这里通过对菜单的翻译来带大家了解翻译模块

Step1 新增翻译记录

切换应用到translate模块,点击新增翻译。

  1. 选择新增翻译生效模块

  2. 选择翻译的模型为:菜单模型

  3. 源语言选择中文,目标选择English

  4. 添加翻译项目:

    1. 源术语为:商店

    2. 翻译值为:shop

    3. 状态为:激活

image.png

Step2 查看效果

应用切换到Demo模块,在右上角切换语言至英语

image.png

后端翻译(自定义模型的翻译)

在前面菜单的翻译中,似乎我们什么都没做就可以正常通过翻译模块完成多语言的切换了。是不是真如我们想象的一样,当然不是。是因为Menu模型的displayName字段加上@Field(translate = true)注解。

Step1 为PetType模型的name字段增加翻译注解

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.IdModel;

@Model.MultiTable(typeField = "kind")
@Model.model(PetType.MODEL_MODEL)
@Model(displayName="品种",labelFields = {"name"})
public class PetType extends IdModel {

    public static final String MODEL_MODEL="demo.PetType";

    @Field(displayName = "品种名" , translate = true)
    private String name;

    @Field(displayName = "宠物分类")
    private String kind;
}

Step2 重启应用查看效果

  1. 切换应用到translate模块,点击新增翻译

image.png

  1. 切换应用到Demo模块,切换中英文,查看效果

image.png

前端翻译

还记得我们前端第一个自定义动作吗?会弹出“oinone第一个自定义Action,啥也没干”,我们要对它进行翻译。

Step1 修改前端DoNothingActionWidget.ts

  1. import translateValueByKey

  2. 提示语用translateValueByKey加上翻译 const confirmRs = executeConfirm(translateValueByKey(\'oinone第一个自定义Action,啥也没干\')||\'oinone第一个自定义Action,啥也没干\');

    前端更多翻译工具请见前端高级特性-框架之翻译工具

import {
  Action,
  ActionContextType,
  ActionWidget,
  executeConfirm,
  IClientAction,
  SPI,
  ViewType,
  Widget,
  translateValueByKey
} from '@kunlun/dependencies';

@SPI.ClassFactory(ActionWidget.Token({ name: 'demo.doNothing' }))
export class DoNothingActionWidget extends ActionWidget {
  @Widget.Method()
  public async clickAction() {
        const confirmRs =  executeConfirm(translateValueByKey('oinone第一个自定义Action,啥也没干')||'oinone第一个自定义Action,啥也没干');
    }
}

//定义动作元数据
Action.registerAction('*', {
  displayName: '啥也没干',
  name: 'demo.doNothing',
  id: 'demo.doNothing',
  contextType: ActionContextType.ContextFree,
  bindingType: [ViewType.Table]
} as IClientAction);

Step2 新增翻译记录

前端翻译的翻译记录对应的模型可以随意找一个放。但要注意几点:

  1. 不要找有字读配置translate = true的模型,因为会影响后端翻译性能。

  2. 最好统一到一个模型中,便于后续管理。这里大家可以自定义一个无有业务访问且本身无需要翻译的模型来挂载,避免性能损失

image.png

Step3 刷新远程资源生成前端语言文件

image.png

Step4 新增或修改.env

前端在项目根目录下新增或修改.env,可以参考.env.example文件。通过.env文件为前端配置oss文件路径,针对I18N_OSS_URL配置项。真实前端访问翻译语言文件的路径规则为:http://bucket.downloadUrl/mainDir/租户/translate/模块/语言文件

  1. yaml文件中oss配置的文件路径:http://pamirs.oss-cn-hangzhou.aliyuncs.com/upload/demo/

  2. 租户/translate/模块/语言文件 前端会自动根据上下文组织

# 后端api配置
# API_BASE_URL=http://127.0.0.1:8090
# 下面是国际化语言的cdn配置,默认用当前请求链接下的路径: /pamirs/translate/${module}/i18n_${lang}.js
I18N_OSS_URL=http://pamirs.oss-cn-hangzhou.aliyuncs.com/upload/demo

Step5 重启前端应用看效果

对语言进行中英文切换,进入宠狗达人页面,点击【第一个自定义Action】,查看前端翻译效果

image.png

image.png

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9328.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日 am8:10
下一篇 2024年5月23日 am8:12

相关推荐

  • 3.5.7.8 自定义菜单栏

    在业务中,可能会遇到需要对菜单栏的交互或UI做全新设计的需求,这个时候可以自定义菜单栏组件支持。 首先继承平台的CustomMenuWidget 组件,将自己vue文件设置到component处 import { NavMenu, SPI, ViewWidget } from '@kunlun/dependencies'; import Component from './CustomMenu.vue'; @SPI.ClassFactory( ViewWidget.Token({ // 这里的widget跟平台的组件一样,这样才能覆盖平台的组件 widget: 'nav-menu' }) ) export class CustomMenuWidget extends NavMenu { public initialize(props) { super.initialize(props); this.setComponent(Component); return this; } } vue文件中继承平台的props,编写自定义页面代码 export const NavMenuProps = { /** * 当前模块 */ module: { type: Object as PropType<IModule | null> }, /** * 树结构的菜单 */ menus: { type: Array as PropType<IResolvedMenu[]>, default: () => [] }, /** * 菜单类型,现在支持垂直、水平、和内嵌模式三种 */ mode: { type: String as PropType<'vertical' | 'horizontal' | 'inline'>, default: 'inline' }, /** * 菜单栏是否折叠收起 */ collapsed: { type: Boolean, default: false }, /** * 当前展开的 SubMenu 菜单项 key 数组 */ openKeys: { type: Array as PropType<string[]>, default: () => [] }, /** * 当前选中的菜单项 key 数组 */ selectKeys: { type: Array as PropType<string[]>, default: () => [] }, /** * 菜单搜索下拉选中菜单项 */ selectMenuBySearch: { type: Function as PropType<(menuName: String) => void> }, /** * 选中菜单项 */ selectMenu: { type: Function as PropType<(menuName: String) => Promise<void>> }, /** * SubMenu 展开/关闭的回调 */ openChange: { type: Function as PropType<(openKeys: string[]) => void> }, /**…

    2024年5月23日
    1.2K00
  • 庄卓然

    从2009年加入阿里至今,经历了“三淘”时期、天猫时期、双十一,到最后的all in无线手淘时期,几乎是赶上了淘系发展的所有历史性事件。在这个过程中,每一次业务的变革都催生着技术的变迁,倒逼着我们用技术的方式去解决业务问题:在存储、IO、网络等环节满足不了淘系的业务规模时,开始去IOE,最后演化成了阿里云;当业务的规模大到不能通过简单加机器的方式去做调整、当开发的规模大到所有人在一起开发会互相影响的的时候,我们开始做SOA改造,最后演化成了业务中台;在经历了几届双十一后的巨大挑战后,我们开创了里程碑式的全链路压测;在手淘时代,为了解决动态发版问题,我们植入容器概念,搭建了可动态插拔的三层架构,一年实现了500多次的发版;为了同时满足写一套代码就解决多端开发和高并发的性能问题,我们做了weex,最后还捐给了开源社区…… 每一次的业务需求推动技术进步,而技术的进步永远会超出我们的想象! 同为技术宅,我在Oinone身上能清晰地感受到技术演进的脉络,企业在数字化时代,需要一个能快速上手、全面设计、灵活适应且低成本的技术工具,时代的变迁推动了Oinone的诞生。Oinone是一种全新的开发方式,在数字化时代,Oinone在提升研发效率上做出的创新性“低无一体”的设计对传统软件代码开发或者无代码开发一定会有巨大冲击,这种冲击会对软件市场格局造成什么样的变化,我拭目以待。 最后,愿我们这些追光人,在时代的洪流中,都能留下一抹印迹,不辜负时代,不辜负自己。 现任阿里巴巴副总裁,飞猪总裁,曾任阿里大文娱CTO兼优酷COO、淘宝CTO 庄卓然(南天)

    Oinone 7天入门到精通 2024年5月23日
    1.6K00
  • 第1章 揭开面纱,理解Oinone

    本章旨在从以下几个维度逐步揭开Oinone的面纱,让大家了解Oinone的初心与愿景,以及它是如何站在软件领域的巨人肩膀上,结合企业数字化转型的深入,形成全新的理念,帮助企业完成数字化转型。 具体来说,本章会从以下四个方面逐一展开: Oinone的初心与愿景:结合中国软件行业的发展与自身职业发展经历,探讨Oinone为何诞生以及其愿景是什么。 Oinone致敬西方软件行业的新贵odoo:介绍Oinone的灵感来源,探究Oinone与odoo的异同,以及如何从odoo中汲取经验。 从企业转型困境,引出Oinone新的思路:通过剖析企业数字化转型的困境,引出Oinone提出的全新思路,以及如何应对企业数字化转型的挑战。 行业对比,让您从不同视角理解Oinone:通过与同行业产品进行对比,从不同的视角深入理解Oinone的特点和优势。

    Oinone 7天入门到精通 2024年5月23日
    2.8K00
  • 4.1.17 框架之网关协议-GraphQL协议

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。 一个 GraphQL 服务是通过定义类型和类型上的字段来创建的,然后给每个类型上的每个字段提供解析函数。例如,一个 GraphQL 服务告诉我们当前登录用户是 me,这个用户的名称可能像这样: type Query { me: User } type User { id: ID name: String } 图4-1-17-1 GraphQL定义类型和字段示意 一并的还有每个类型上字段的解析函数: function Query_me(request) { return request.auth.user; } function User_name(user) { return user.getName(); } 图4-1-17-2 每个类型上字段的解析函数示意 一旦一个 GraphQL 服务运行起来(通常在 web 服务的一个 URL 上),它就能接收 GraphQL 查询,并验证和执行。接收到的查询首先会被检查确保它只引用了已定义的类型和字段,然后运行指定的解析函数来生成结果。 例如这个查询: { me { name } } 图4-1-17-3 GraphQL查询请求示意 会产生这样的JSON结果: { "me": { "name": "Luke Skywalker" } } 图4-1-17-4 GraphQL查询结果示意 了解更多 https://graphql.cn/learn/

    Oinone 7天入门到精通 2024年5月23日
    1.1K00

Leave a Reply

登录后才能评论

评论列表(2条)

  • xiao3的头像
    xiao3 2024年11月25日 am10:43

    只支持英语吗?如何添加其他语种?

    • shao的头像
      shao 2024年11月25日 pm5:24

      @xiao3支持其他的国家的语言,需要在资源里面创建,如果有其他的疑问,也可以群内联系我们哈