feat: ship the interface in eight languages, with per-language plurals and mirroring

This commit is contained in:
randogoth 2026-10-11 14:54:43 +03:00
parent 6de6672ae3
commit a4a49f41d7
28 changed files with 1795 additions and 32 deletions

View file

@ -82,6 +82,7 @@ class ReaderSettings extends Table {
RealColumn get fontScale => real().withDefault(const Constant(1.0))();
TextColumn get themeMode => text().withDefault(const Constant('system'))();
TextColumn get variant => text().withDefault(const Constant('site'))();
TextColumn get language => text().withDefault(const Constant('system'))();
@override
Set<Column> get primaryKey => {id};
@ -116,13 +117,27 @@ class MewsDatabase extends _$MewsDatabase {
MewsDatabase.test(super.executor);
@override
int get schemaVersion => 2;
int get schemaVersion => 3;
/// Pre-release: the entry store replaces the old list of seen entry URLs and
/// the library tables gain real primary keys, so an existing database is
/// recreated rather than migrated.
@override
MigrationStrategy get migration => destructiveFallback;
MigrationStrategy get migration => MigrationStrategy(
onCreate: (m) => m.createAll(),
onUpgrade: (m, from, to) async {
// Version 1 predates the entry store and the library tables' real
// primary keys. Nothing of it is worth carrying, so it is recreated;
// later versions only gain columns and keep what the reader has.
if (from < 2) {
for (final entity in allSchemaEntities.toList().reversed) {
await m.drop(entity);
}
await m.createAll();
return;
}
if (from < 3) {
await m.addColumn(readerSettings, readerSettings.language);
}
},
);
static QueryExecutor _open() => LazyDatabase(() async {
final dir = await getApplicationDocumentsDirectory();
@ -522,6 +537,7 @@ class MewsDatabase extends _$MewsDatabase {
required double fontScale,
required String themeMode,
required String variant,
required String language,
}) =>
into(readerSettings).insert(
ReaderSettingsCompanion.insert(
@ -530,6 +546,7 @@ class MewsDatabase extends _$MewsDatabase {
fontScale: Value(fontScale),
themeMode: Value(themeMode),
variant: Value(variant),
language: Value(language),
),
mode: InsertMode.insertOrReplace);

View file

@ -1711,6 +1711,18 @@ class $ReaderSettingsTable extends ReaderSettings
requiredDuringInsert: false,
defaultValue: const Constant('site'),
);
static const VerificationMeta _languageMeta = const VerificationMeta(
'language',
);
@override
late final GeneratedColumn<String> language = GeneratedColumn<String>(
'language',
aliasedName,
false,
type: DriftSqlType.string,
requiredDuringInsert: false,
defaultValue: const Constant('system'),
);
@override
List<GeneratedColumn> get $columns => [
id,
@ -1718,6 +1730,7 @@ class $ReaderSettingsTable extends ReaderSettings
fontScale,
themeMode,
variant,
language,
];
@override
String get aliasedName => _alias ?? actualTableName;
@ -1758,6 +1771,12 @@ class $ReaderSettingsTable extends ReaderSettings
variant.isAcceptableOrUnknown(data['variant']!, _variantMeta),
);
}
if (data.containsKey('language')) {
context.handle(
_languageMeta,
language.isAcceptableOrUnknown(data['language']!, _languageMeta),
);
}
return context;
}
@ -1787,6 +1806,10 @@ class $ReaderSettingsTable extends ReaderSettings
DriftSqlType.string,
data['${effectivePrefix}variant'],
)!,
language: attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}language'],
)!,
);
}
@ -1802,12 +1825,14 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
final double fontScale;
final String themeMode;
final String variant;
final String language;
const ReaderSetting({
required this.id,
required this.font,
required this.fontScale,
required this.themeMode,
required this.variant,
required this.language,
});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
@ -1817,6 +1842,7 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
map['font_scale'] = Variable<double>(fontScale);
map['theme_mode'] = Variable<String>(themeMode);
map['variant'] = Variable<String>(variant);
map['language'] = Variable<String>(language);
return map;
}
@ -1827,6 +1853,7 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
fontScale: Value(fontScale),
themeMode: Value(themeMode),
variant: Value(variant),
language: Value(language),
);
}
@ -1841,6 +1868,7 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
fontScale: serializer.fromJson<double>(json['fontScale']),
themeMode: serializer.fromJson<String>(json['themeMode']),
variant: serializer.fromJson<String>(json['variant']),
language: serializer.fromJson<String>(json['language']),
);
}
@override
@ -1852,6 +1880,7 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
'fontScale': serializer.toJson<double>(fontScale),
'themeMode': serializer.toJson<String>(themeMode),
'variant': serializer.toJson<String>(variant),
'language': serializer.toJson<String>(language),
};
}
@ -1861,12 +1890,14 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
double? fontScale,
String? themeMode,
String? variant,
String? language,
}) => ReaderSetting(
id: id ?? this.id,
font: font ?? this.font,
fontScale: fontScale ?? this.fontScale,
themeMode: themeMode ?? this.themeMode,
variant: variant ?? this.variant,
language: language ?? this.language,
);
ReaderSetting copyWithCompanion(ReaderSettingsCompanion data) {
return ReaderSetting(
@ -1875,6 +1906,7 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
fontScale: data.fontScale.present ? data.fontScale.value : this.fontScale,
themeMode: data.themeMode.present ? data.themeMode.value : this.themeMode,
variant: data.variant.present ? data.variant.value : this.variant,
language: data.language.present ? data.language.value : this.language,
);
}
@ -1885,13 +1917,15 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
..write('font: $font, ')
..write('fontScale: $fontScale, ')
..write('themeMode: $themeMode, ')
..write('variant: $variant')
..write('variant: $variant, ')
..write('language: $language')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, font, fontScale, themeMode, variant);
int get hashCode =>
Object.hash(id, font, fontScale, themeMode, variant, language);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@ -1900,7 +1934,8 @@ class ReaderSetting extends DataClass implements Insertable<ReaderSetting> {
other.font == this.font &&
other.fontScale == this.fontScale &&
other.themeMode == this.themeMode &&
other.variant == this.variant);
other.variant == this.variant &&
other.language == this.language);
}
class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
@ -1909,12 +1944,14 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
final Value<double> fontScale;
final Value<String> themeMode;
final Value<String> variant;
final Value<String> language;
const ReaderSettingsCompanion({
this.id = const Value.absent(),
this.font = const Value.absent(),
this.fontScale = const Value.absent(),
this.themeMode = const Value.absent(),
this.variant = const Value.absent(),
this.language = const Value.absent(),
});
ReaderSettingsCompanion.insert({
this.id = const Value.absent(),
@ -1922,6 +1959,7 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
this.fontScale = const Value.absent(),
this.themeMode = const Value.absent(),
this.variant = const Value.absent(),
this.language = const Value.absent(),
});
static Insertable<ReaderSetting> custom({
Expression<int>? id,
@ -1929,6 +1967,7 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
Expression<double>? fontScale,
Expression<String>? themeMode,
Expression<String>? variant,
Expression<String>? language,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@ -1936,6 +1975,7 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
if (fontScale != null) 'font_scale': fontScale,
if (themeMode != null) 'theme_mode': themeMode,
if (variant != null) 'variant': variant,
if (language != null) 'language': language,
});
}
@ -1945,6 +1985,7 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
Value<double>? fontScale,
Value<String>? themeMode,
Value<String>? variant,
Value<String>? language,
}) {
return ReaderSettingsCompanion(
id: id ?? this.id,
@ -1952,6 +1993,7 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
fontScale: fontScale ?? this.fontScale,
themeMode: themeMode ?? this.themeMode,
variant: variant ?? this.variant,
language: language ?? this.language,
);
}
@ -1973,6 +2015,9 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
if (variant.present) {
map['variant'] = Variable<String>(variant.value);
}
if (language.present) {
map['language'] = Variable<String>(language.value);
}
return map;
}
@ -1983,7 +2028,8 @@ class ReaderSettingsCompanion extends UpdateCompanion<ReaderSetting> {
..write('font: $font, ')
..write('fontScale: $fontScale, ')
..write('themeMode: $themeMode, ')
..write('variant: $variant')
..write('variant: $variant, ')
..write('language: $language')
..write(')'))
.toString();
}
@ -3362,6 +3408,7 @@ typedef $$ReaderSettingsTableCreateCompanionBuilder =
Value<double> fontScale,
Value<String> themeMode,
Value<String> variant,
Value<String> language,
});
typedef $$ReaderSettingsTableUpdateCompanionBuilder =
ReaderSettingsCompanion Function({
@ -3370,6 +3417,7 @@ typedef $$ReaderSettingsTableUpdateCompanionBuilder =
Value<double> fontScale,
Value<String> themeMode,
Value<String> variant,
Value<String> language,
});
class $$ReaderSettingsTableFilterComposer
@ -3405,6 +3453,11 @@ class $$ReaderSettingsTableFilterComposer
column: $table.variant,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get language => $composableBuilder(
column: $table.language,
builder: (column) => ColumnFilters(column),
);
}
class $$ReaderSettingsTableOrderingComposer
@ -3440,6 +3493,11 @@ class $$ReaderSettingsTableOrderingComposer
column: $table.variant,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get language => $composableBuilder(
column: $table.language,
builder: (column) => ColumnOrderings(column),
);
}
class $$ReaderSettingsTableAnnotationComposer
@ -3465,6 +3523,9 @@ class $$ReaderSettingsTableAnnotationComposer
GeneratedColumn<String> get variant =>
$composableBuilder(column: $table.variant, builder: (column) => column);
GeneratedColumn<String> get language =>
$composableBuilder(column: $table.language, builder: (column) => column);
}
class $$ReaderSettingsTableTableManager
@ -3505,12 +3566,14 @@ class $$ReaderSettingsTableTableManager
Value<double> fontScale = const Value.absent(),
Value<String> themeMode = const Value.absent(),
Value<String> variant = const Value.absent(),
Value<String> language = const Value.absent(),
}) => ReaderSettingsCompanion(
id: id,
font: font,
fontScale: fontScale,
themeMode: themeMode,
variant: variant,
language: language,
),
createCompanionCallback:
({
@ -3519,12 +3582,14 @@ class $$ReaderSettingsTableTableManager
Value<double> fontScale = const Value.absent(),
Value<String> themeMode = const Value.absent(),
Value<String> variant = const Value.absent(),
Value<String> language = const Value.absent(),
}) => ReaderSettingsCompanion.insert(
id: id,
font: font,
fontScale: fontScale,
themeMode: themeMode,
variant: variant,
language: language,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), BaseReferences(db, table, e)))