数据化存储菜单,国际化方案

发布于:2025-09-15 ⋅ 阅读:(22) ⋅ 点赞:(0)

django

class Menu(models.Model):
    parent_id = models.BigIntegerField(default=0, verbose_name='父菜单ID')
    name = models.CharField(max_length=50, verbose_name='菜单名称')
    icon = models.CharField(max_length=50, blank=True, null=True, verbose_name='菜单图标')
    path = models.CharField(max_length=100, blank=True, null=True, verbose_name='路由路径')
    component = models.CharField(max_length=100, blank=True, null=True, verbose_name='组件路径')
    sort = models.IntegerField(default=0, verbose_name='排序')
    visible = models.SmallIntegerField(default=1, verbose_name='是否显示')
    status = models.SmallIntegerField(default=1, verbose_name='状态')
    creator_id = models.BigIntegerField(blank=True, null=True, verbose_name='创建人ID')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    is_deleted = models.SmallIntegerField(default=0, verbose_name='删除标志(0未删除,1删除)')

    class Meta:
        db_table = 'menus'
        verbose_name = '菜单'
        indexes = [
            models.Index(fields=['parent_id']),
            models.Index(fields=['sort']),
            models.Index(fields=['status']),
        ]

像菜单模型直接将 name 字段写死在数据库中,是不支持国际化(i18n)的。如果你要做多语言系统,比如中英文切换,菜单名称就无法动态适配。

国际化菜单的常见方案

方案一:菜单名称只存“标识符”,前端根据语言包翻译(推荐)

name = models.CharField(max_length=50, verbose_name='菜单标识符')  # 如 "menu.system.user"

然后前端使用语言包:

{
  "menu.system.user": "用户管理",
  "menu.system.role": "角色管理"
}

优点:

  • 菜单结构不变,语言切换只影响前端显示。

  • 支持任意语言扩展。

  • 前后端解耦,更灵活。

方案二:菜单表新增多语言字段(如 name_en、name_zh)

name_zh = models.CharField(max_length=50)
name_en = models.CharField(max_length=50)

然后后端根据用户语言返回对应字段。

优点:

  • 后端控制显示语言,适合服务端渲染。

  • 可用于导出、打印等场景。

缺点:

  • 数据库字段膨胀,维护成本高。

  • 每加一种语言就要加一列。

方案三:单独建一个菜单翻译表(menu_translations)

class MenuTranslation(models.Model):
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE)
    lang = models.CharField(max_length=10)  # 如 "zh", "en"
    name = models.CharField(max_length=50)

优点:

  • 数据结构规范,支持无限语言。

  • 可动态添加翻译,不改主表结构。

缺点:

  • 查询时需要 join 或缓存。

  • 实现稍复杂。

推荐做法(前后端分离项目)

菜单表只存标识符,前端用 i18n 语言包翻译 是最轻量、最灵活的方案。

你只需把菜单 name 改成:

name = models.CharField(max_length=50, verbose_name='菜单标识符')  # 如 "menu.system.user"

然后前端 Vue 使用:

this.$t(menu.name)  // 自动翻译

语言包结构:

{
  "menu.system.user": "用户管理",
  "menu.system.role": "角色管理"
}