How can I load translations from Firestore and then use them for GetX translations/internationalization?
I want to have a language collection inside two documents (US & DE) that contain all the string value translations. Therefore instead of this...
import 'package:get/get.dart';
class Messages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
'hello': 'Hello World',
},
'de_DE': {
'hello': 'Hallo Welt',
}
};
}
I want something like this...
//Get data from Firestore as dataFromFirestore_US
& dataFromFirestore_DE
import 'package:get/get.dart';
class Messages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
dataFromFirestore_US,
},
'de_DE': {
dataFromFirestore_DE,
}
};
}
I tried loading data from Firestore and get the error message:
type 'Null' is not a subtype of type 'Map<String, String>' See also: https://flutter.dev/docs/ testing/errors
To get this error:
I have a LanguageController.dart file that loads the language as follows:
final languages = LanguageModel().obs;
Future getLanguages() async {
QuerySnapshot data =
await FirebaseFirestore.instance.collection("languages").get();
data.docs.forEach((doc) {
if (doc.id == "en") {
var enLang = "'void': 'GO ONLINE'";
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
for (String key in data.keys) {
enLang = '$enLang, "${key.toString()}": "${data[key].toString()}"';
}
languages.value.en = enLang;
en.value = enLang;
}
});
}
The LanguageModel.dart looks like this:
class LanguageModel {
dynamic en;
dynamic se;
LanguageModel({this.en, this.se});
Map<String, Map<String, String>> toJson() {
return {
"en": en,
"se": se,
};
}
}
The Translation part looks like:
static final locale = Locale('se', 'SE');
static final fallbackLocale = Locale('en', 'US');
static final langs = [
'Swedish',
'English',
];
static final locales = [
Locale('se', 'SE'),
Locale('en', 'US'),
];
@override
// TODO: implement keys
@override
final LanguageController l = Get.find();
@override
Map<String, Map<String, String>> get keys => {
'en_US': l.languages.value.en,
'se_SE': seSE,
};
// Gets locale from language, and updates the locale
void changeLocale(String lang) {
final locale = _getLocaleFromLanguage(lang);
Get.updateLocale(locale!);
}
Any help or advice would be appreciated.
I managed to get everything working well and can switch between languages loaded from Firestore, I hope this helps anyone else wanting to do the same.
SOLUTION
1. Firestore collection, documents, and data
Create a collection called languages, I need English and Swedish
therefore I have 2 documents called en and se containing the
language data as strings such as: hello: 'Hello'
2. LanguageController.dart (Get data from Firestore)
import 'package:get/get.dart'; import
'package:cloud_firestore/cloud_firestore.dart';
class LanguageController extends GetxController {
RxString language = "Swedish".obs;
RxMap<String, String> langEN = <String, String>{}.obs;
RxMap<String, String> langSE = <String, String>{}.obs;
void updateLanguage(String data) {
language.value = data;
}
Future getLanguages() async {
//Get all languages in languages collection
QuerySnapshot data =
await FirebaseFirestore.instance.collection("languages").get();
data.docs.forEach((doc) {
if (doc.id == "en") {
final data = doc.data() as Map<String, dynamic>;
for (String key in data.keys) {
langEN['${key.toString()}'] = '${data[key].toString()}';
}
} else if (doc.id == "se") {
final data = doc.data() as Map<String, dynamic>;
for (String key in data.keys) {
langSE['${key.toString()}'] = '${data[key].toString()}';
}
}
});
}
}
3. languages.dart
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/LanguageController.dart';
class Languages extends Translations {
// Default locale
static final locale = Locale('se', 'SE');
// fallbackLocale saves the day when the locale gets in trouble
static final fallbackLocale = Locale('en', 'US');
// Supported languages
// Needs to be same order with locales
static final langs = [
'Swedish',
'English',
];
// Supported locales
// Needs to be same order with langs
static final locales = [
Locale('se', 'SE'),
Locale('en', 'US'),
];
final LanguageController l = Get.find();
@override
Map<String, Map<String, String>> get keys =>
{'en_US': l.langEN, 'se_SE': l.langSE};
// Gets locale from language, and updates the locale
void changeLocale(String lang) {
final locale = _getLocaleFromLanguage(lang);
Get.updateLocale(locale!);
}
// Finds language in `langs` list and returns it as Locale
Locale? _getLocaleFromLanguage(String lang) {
for (int i = 0; i < langs.length; i++) {
if (lang == langs[i]) return locales[i];
}
return Get.locale;
}
}
If anyone has any issues comment and I will try and help out.