feat(settings): introduce language model

task: #6416
This commit is contained in:
Patryk Osmaczko 2022-07-15 14:38:50 +02:00 committed by osmaczko
parent 81cda65b20
commit 13a6407a75
7 changed files with 185 additions and 7 deletions

View File

@ -20,4 +20,7 @@ proc delete*(self: Controller) =
discard
proc changeLanguage*(self: Controller, locale: string) =
self.languageService.setLanguage(locale)
self.languageService.setLanguage(locale)
proc getLocales*(self: Controller): seq[string] =
self.languageService.locales()

View File

@ -0,0 +1,24 @@
type
Item* = object
locale: string
name: string
native: string
flag: string # unicode emoji
proc initItem*(locale, name, native, flag: string): Item =
result.locale = locale
result.name = name
result.native = native
result.flag = flag
proc locale*(self: Item): string {.inline.} =
self.locale
proc name*(self: Item): string {.inline.} =
self.locale
proc native*(self: Item): string {.inline.} =
self.locale
proc flag*(self: Item): string {.inline.} =
self.locale

View File

@ -0,0 +1,44 @@
import tables
type
Description* = object
name*: string
native*: string
flag*: string
let localeDescriptionTable* = {
"ar": Description(name: "Arabic", native: "العربية", flag: ""),
"bn": Description(name: "Bengali", native: "বাংলা", flag: "X"),
"de": Description(name: "German", native: "Deutsch", flag: "🇩🇪"),
"el": Description(name: "Greek", native: "Ελληνικά", flag: "🇬🇷"),
"en": Description(name: "English", native: "English", flag: "🏴󠁧󠁢󠁥󠁮󠁧󠁿"),
"en_US": Description(name: "English (United States)", native: "English (United States)", flag: "🇺🇸"),
"es": Description(name: "Spanish", native: "Español", flag: "🇪🇸"),
"es_419": Description(name: "Spanish (Latin America)", native: "Español (Latinoamerica)", flag: ""),
"es_AR": Description(name: "Spanish (Argentina)", native: "Español (Argentina)", flag: "🇦🇷"),
"fa": Description(name: "Persian", native: "فارسی", flag: "🇮🇷"),
"fr": Description(name: "French", native: "Français", flag: "🇫🇷"),
"he": Description(name: "Hebrew", native: "עברית'", flag: "🇮🇱"),
"he": Description(name: "Hindi", native: "हिन्दी", flag: "🇮🇳"),
"hu": Description(name: "Hungarian", native: "Magyar", flag: "🇭🇺"),
"id": Description(name: "Indonesian", native: "Bahasa Indonesia", flag: "🇮🇩"),
"it": Description(name: "Italian", native: "Italiano", flag: "🇮🇹"),
"ja": Description(name: "Japanese", native: "日本語", flag: "🇯🇵"),
"ko": Description(name: "Korean", native: "한국어", flag: "🇰🇷"),
"ms": Description(name: "Malay", native: "Bahasa Melayu", flag: "🇲🇾"),
"ne": Description(name: "Nepali", native: "नेपाली", flag: "🇳🇵"),
"nl": Description(name: "Dutch", native: "Nederlands", flag: "🇳🇱"),
"pl": Description(name: "Polish", native: "Polski", flag: "🇵🇱"),
"pt": Description(name: "Portuguese", native: "Português", flag: "🇵🇹"),
"pt_BR": Description(name: "Portuguese (Brazil)", native: "Português (Brasil)", flag: "🇧🇷"),
"ru": Description(name: "Russian", native: "Русский", flag: "🇷🇺"),
"sv": Description(name: "Swedish", native: "Svenska", flag: "🇸🇪"),
"th": Description(name: "Thai", native: "ไทย / Phasa Thai", flag: "🇹🇭"),
"tl": Description(name: "Tagalog", native: "Tagalog", flag: "🇵🇭"),
"tr": Description(name: "Turkish", native: "Türkçe", flag: "🇹🇷"),
"ug": Description(name: "Uyghur", native: "Uyƣurqə / ئۇيغۇرچە", flag: "X"),
"uk": Description(name: "Ukrainian", native: "Українська", flag: "🇺🇦"),
"vi": Description(name: "Vietnamese", native: "Việtnam", flag: "🇻🇳"),
"zh_CN": Description(name: "Chinese (China)", native: "中文(中國)", flag: "🇨🇳"),
"zh_TW": Description(name: "Chinese (Taiwan)", native: "中文(台灣)", flag: "🇹🇼"),
}.toTable()

View File

@ -0,0 +1,62 @@
import NimQml, tables
import item
type
ModelRole {.pure.} = enum
Locale = UserRole + 1
Name
Native
Flag
QtObject:
type
Model* = ref object of QAbstractListModel
items: seq[Item]
proc delete(self: Model) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: Model) =
self.QAbstractListModel.setup
proc newModel*(): Model =
new(result, delete)
result.setup
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()
method rowCount(self: Model, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: Model): Table[int, string] =
{
ModelRole.Locale.int: "locale",
ModelRole.Name.int: "name",
ModelRole.Native.int: "native",
ModelRole.Flag.int: "flag",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Locale:
result = newQVariant(item.locale)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.Native:
result = newQVariant(item.native)
of ModelRole.Flag:
result = newQVariant(item.flag)

View File

@ -1,6 +1,6 @@
import NimQml, Tables
import NimQml, tables, sequtils, sugar, chronicles
import ./io_interface, ./view, ./controller
import io_interface, view, controller, item, model, locale_table
import ../io_interface as delegate_interface
import ../../../../global/global_singleton
@ -16,7 +16,8 @@ type
viewVariant: QVariant
moduleLoaded: bool
proc newModule*(delegate: delegate_interface.AccessInterface, languageService: language_service.Service): Module =
proc newModule*(delegate: delegate_interface.AccessInterface,
languageService: language_service.Service): Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
@ -24,6 +25,23 @@ proc newModule*(delegate: delegate_interface.AccessInterface, languageService: l
result.controller = controller.newController(result, languageService)
result.moduleLoaded = false
proc populateLanguageModel(self: Module) =
var items: seq[Item]
for locale in self.controller.getLocales():
if localeDescriptionTable.contains(locale):
let localeDescr = localeDescriptionTable[locale]
items.add(initItem(
locale = locale,
name = localeDescr.name,
native = localeDescr.native,
flag = localeDescr.flag
))
else:
warn "missing locale details", locale
self.view.model().setItems(items)
method delete*(self: Module) =
self.view.delete
@ -35,6 +53,7 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
self.populateLanguageModel()
self.moduleLoaded = true
self.delegate.languageModuleDidLoad()

View File

@ -1,24 +1,38 @@
import NimQml
# import ./controller_interface
import ./io_interface
import io_interface, model
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
model: Model
modelVariant: QVariant
proc delete*(self: View) =
self.QObject.delete
self.model.delete
self.modelVariant.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
result.model = newModel()
result.modelVariant = newQVariant(result.model)
proc load*(self: View) =
self.delegate.viewDidLoad()
proc model*(self: View): Model =
return self.model
proc getModel(self: View): QVariant {.slot.} =
return self.modelVariant
QtProperty[QVariant] model:
read = getModel
proc changeLocale*(self: View, locale: string) {.slot.} =
self.delegate.changeLanguage(locale)

View File

@ -1,5 +1,5 @@
import NimQml
import json, json_serialization, sequtils, chronicles, os, strformat
import json, json_serialization, sequtils, chronicles, os, strformat, re
import ../../../app/global/global_singleton
logScope:
@ -9,6 +9,7 @@ type
Service* = ref object of RootObj
i18nPath: string
shouldRetranslate: bool
locales: seq[string]
proc delete*(self: Service) =
discard
@ -17,6 +18,12 @@ proc newService*(): Service =
result = Service()
result.shouldRetranslate = not defined(linux)
proc obtainLocales(dir: string): seq[string] =
let localeRe = re".*qml_(.*).qm"
for file in walkFiles dir & "/*.qm":
if file =~ localeRe:
result.add(matches[0])
proc init*(self: Service) =
try:
self.i18nPath = ""
@ -29,6 +36,8 @@ proc init*(self: Service) =
elif (defined(linux)):
self.i18nPath = joinPath(getAppDir(), "../i18n")
self.locales = obtainLocales(self.i18nPath)
let locale = singletonInstance.localAppSettings.getLocale()
singletonInstance.engine.setTranslationPackage(joinPath(self.i18nPath, fmt"qml_{locale}.qm"), self.shouldRetranslate)
@ -43,3 +52,6 @@ proc setLanguage*(self: Service, locale: string) =
singletonInstance.localAppSettings.setLocale(locale)
singletonInstance.engine.setTranslationPackage(joinPath(self.i18nPath, fmt"qml_{locale}.qm"), self.shouldRetranslate)
proc locales*(self: Service): seq[string] =
self.locales