feat(i18n): full RTL/CJK support — fonts, Japanese locale, directional fixes
Bundle Noto Sans Arabic + Noto Sans JP (SIL OFL 1.1) as per-glyph fallbacks for both the UI text theme and every generated PDF, so RTL (Arabic) and CJK render on all platforms — including desktop, where the system font may lack them — instead of tofu. A shared pdf_fonts.dart centralizes the PDF theme and the three label/catalog/recovery services reuse it. Add Japanese (ja) as the CJK reference locale — fittingly, the app's own name is Japanese (種, tane, 'seed'). Core strings translated; the rest fall back to English via slang. Wired into supportedLocales (automatic) and the settings picker. Fix three physical Alignment.centerLeft -> AlignmentDirectional.centerStart in variety_detail_screen, and make month-abbreviation and avatar-initial truncation grapheme-safe (.characters) so CJK text is never cut mid-character. Tests: CJK/Arabic PDF glyph render, ja locale resolution + English fallback. The chat-bubble mirroring flagged by the audit was verified correct (already respects Directionality) and left unchanged.
This commit is contained in:
parent
41ea6735d2
commit
baa8867287
31 changed files with 686 additions and 104 deletions
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
|
||||
import 'file_service.dart';
|
||||
import 'pdf_fonts.dart';
|
||||
|
||||
/// Renders the printable recovery sheet — a QR plus the typed code and short
|
||||
/// instructions ("keep two paper copies, like your best seed"). All strings
|
||||
|
|
@ -19,22 +19,15 @@ class RecoverySheetService {
|
|||
required String intro,
|
||||
required String code,
|
||||
}) async {
|
||||
final base = pw.Font.ttf(
|
||||
await rootBundle.load('assets/fonts/DejaVuSans.ttf'),
|
||||
);
|
||||
final bold = pw.Font.ttf(
|
||||
await rootBundle.load('assets/fonts/DejaVuSans-Bold.ttf'),
|
||||
);
|
||||
final doc = pw.Document(
|
||||
theme: pw.ThemeData.withFont(base: base, bold: bold),
|
||||
);
|
||||
final fonts = await loadPdfFonts();
|
||||
final doc = pw.Document(theme: fonts.theme);
|
||||
doc.addPage(
|
||||
pw.Page(
|
||||
pageFormat: PdfPageFormat.a4,
|
||||
build: (context) => pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
pw.Text(title, style: pw.TextStyle(font: bold, fontSize: 20)),
|
||||
pw.Text(title, style: pw.TextStyle(font: fonts.bold, fontSize: 20)),
|
||||
pw.SizedBox(height: 12),
|
||||
pw.Text(intro, style: const pw.TextStyle(fontSize: 11)),
|
||||
pw.SizedBox(height: 24),
|
||||
|
|
@ -54,7 +47,7 @@ class RecoverySheetService {
|
|||
child: pw.Text(
|
||||
code,
|
||||
textAlign: pw.TextAlign.center,
|
||||
style: pw.TextStyle(font: bold, fontSize: 12),
|
||||
style: pw.TextStyle(font: fonts.bold, fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue