[feat] add i18n localization: en/zh; add peers display; ui refresh
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
"statusRunning": "Running",
|
||||
"statusStopped": "Stopped",
|
||||
"refreshStatusTooltip": "Refresh Status",
|
||||
"startButton": "Start",
|
||||
"restartButton": "Restart",
|
||||
"stopButton": "Stop",
|
||||
"statusDetailsTitle": "ZeroTier Details",
|
||||
"nodeAddressLabel": "Node Address",
|
||||
"softwareVersionLabel": "Software Version",
|
||||
"onlineStatusLabel": "Online Status",
|
||||
"onlineStatusOnline": "Online",
|
||||
"onlineStatusOffline": "Offline",
|
||||
"primaryPortLabel": "Primary Port",
|
||||
"listeningAddressesLabel": "Listening Addresses:",
|
||||
"noListeningAddresses": "None",
|
||||
|
||||
"leaveNetworkConfirmationTitle": "Leave Network?",
|
||||
"leaveNetworkConfirmationText": "Are you sure you want to leave network {networkId}?",
|
||||
"@leaveNetworkConfirmationText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"confirmButton": "Confirm",
|
||||
"cancelButton": "Cancel",
|
||||
"networkIdLabel": "Network ID",
|
||||
"networkIdHint": "Enter 16-character Network ID",
|
||||
"invalidNetworkIdTitle": "Invalid Network ID",
|
||||
"invalidNetworkIdText": "Please enter a 16-character network ID.",
|
||||
"joinButton": "Join",
|
||||
"networksTitle": "Networks",
|
||||
"refreshNetworksTooltip": "Refresh Network List",
|
||||
"noNetworksJoined": "No networks joined",
|
||||
"copiedToClipboard": "Copied {networkId} to clipboard!",
|
||||
"@copiedToClipboard": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyTooltip": "Copy",
|
||||
"leaveTooltip": "Leave",
|
||||
"clearInputTooltip": "Clear input",
|
||||
"peersFeatureComingSoon": "Peers feature coming soon",
|
||||
"noPeersFound": "No peers found",
|
||||
|
||||
"navBarLabelStatus": "Status",
|
||||
"navBarLabelNetworks": "Networks",
|
||||
"navBarLabelPeers": "Peers",
|
||||
"appBarTitleStatus": "Status",
|
||||
"appBarTitleNetworks": "Networks",
|
||||
"appBarTitlePeers": "Peers",
|
||||
|
||||
"joinNetworkSuccessText": "Successfully joined network {networkId}!",
|
||||
"@joinNetworkSuccessText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"joinNetworkErrorText": "Failed to join network: {error}",
|
||||
"@joinNetworkErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "Connection timed out"
|
||||
}
|
||||
}
|
||||
},
|
||||
"leaveNetworkSuccessText": "Successfully left network {networkId}.",
|
||||
"@leaveNetworkSuccessText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"leaveNetworkErrorText": "Failed to leave network: {error}",
|
||||
"@leaveNetworkErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "Permission denied"
|
||||
}
|
||||
}
|
||||
},
|
||||
"refreshButtonLabel": "Retry",
|
||||
|
||||
"loadPeersErrorText": "Failed to load peers: {error}",
|
||||
"@loadPeersErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "Network error"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"loadNetworksErrorText": "Failed to load networks: {error}",
|
||||
"@loadNetworksErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "Network error"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"serviceNotRunning": "ZeroTier service is not running",
|
||||
|
||||
"moduleNotRunning": "ZeroTier Magisk module is not running. Please check if you have installed the ZeroTier Magisk module.",
|
||||
|
||||
"peerTunneled": "Relayed",
|
||||
"peerDirect": "Direct"
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
import 'app_localizations_en.dart';
|
||||
import 'app_localizations_zh.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// Callers can lookup localized strings with an instance of AppLocalizations
|
||||
/// returned by `AppLocalizations.of(context)`.
|
||||
///
|
||||
/// Applications need to include `AppLocalizations.delegate()` in their app's
|
||||
/// `localizationDelegates` list, and the locales they support in the app's
|
||||
/// `supportedLocales` list. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// import 'l10n/app_localizations.dart';
|
||||
///
|
||||
/// return MaterialApp(
|
||||
/// localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
/// supportedLocales: AppLocalizations.supportedLocales,
|
||||
/// home: MyApplicationHome(),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ## Update pubspec.yaml
|
||||
///
|
||||
/// Please make sure to update your pubspec.yaml to include the following
|
||||
/// packages:
|
||||
///
|
||||
/// ```yaml
|
||||
/// dependencies:
|
||||
/// # Internationalization support.
|
||||
/// flutter_localizations:
|
||||
/// sdk: flutter
|
||||
/// intl: any # Use the pinned version from flutter_localizations
|
||||
///
|
||||
/// # Rest of dependencies
|
||||
/// ```
|
||||
///
|
||||
/// ## iOS Applications
|
||||
///
|
||||
/// iOS applications define key application metadata, including supported
|
||||
/// locales, in an Info.plist file that is built into the application bundle.
|
||||
/// To configure the locales supported by your app, you’ll need to edit this
|
||||
/// file.
|
||||
///
|
||||
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
|
||||
/// Then, in the Project Navigator, open the Info.plist file under the Runner
|
||||
/// project’s Runner folder.
|
||||
///
|
||||
/// Next, select the Information Property List item, select Add Item from the
|
||||
/// Editor menu, then select Localizations from the pop-up menu.
|
||||
///
|
||||
/// Select and expand the newly-created Localizations item then, for each
|
||||
/// locale your application supports, add a new item and select the locale
|
||||
/// you wish to add from the pop-up menu in the Value field. This list should
|
||||
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
|
||||
/// property.
|
||||
abstract class AppLocalizations {
|
||||
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
final String localeName;
|
||||
|
||||
static AppLocalizations of(BuildContext context) {
|
||||
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
|
||||
}
|
||||
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
|
||||
|
||||
/// A list of this localizations delegate along with the default localizations
|
||||
/// delegates.
|
||||
///
|
||||
/// Returns a list of localizations delegates containing this delegate along with
|
||||
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
|
||||
/// and GlobalWidgetsLocalizations.delegate.
|
||||
///
|
||||
/// Additional delegates can be added by appending to this list in
|
||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('en'),
|
||||
Locale('zh')
|
||||
];
|
||||
|
||||
/// No description provided for @statusRunning.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Running'**
|
||||
String get statusRunning;
|
||||
|
||||
/// No description provided for @statusStopped.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Stopped'**
|
||||
String get statusStopped;
|
||||
|
||||
/// No description provided for @refreshStatusTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Refresh Status'**
|
||||
String get refreshStatusTooltip;
|
||||
|
||||
/// No description provided for @startButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Start'**
|
||||
String get startButton;
|
||||
|
||||
/// No description provided for @restartButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Restart'**
|
||||
String get restartButton;
|
||||
|
||||
/// No description provided for @stopButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Stop'**
|
||||
String get stopButton;
|
||||
|
||||
/// No description provided for @statusDetailsTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'ZeroTier Details'**
|
||||
String get statusDetailsTitle;
|
||||
|
||||
/// No description provided for @nodeAddressLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Node Address'**
|
||||
String get nodeAddressLabel;
|
||||
|
||||
/// No description provided for @softwareVersionLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Software Version'**
|
||||
String get softwareVersionLabel;
|
||||
|
||||
/// No description provided for @onlineStatusLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Online Status'**
|
||||
String get onlineStatusLabel;
|
||||
|
||||
/// No description provided for @onlineStatusOnline.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Online'**
|
||||
String get onlineStatusOnline;
|
||||
|
||||
/// No description provided for @onlineStatusOffline.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Offline'**
|
||||
String get onlineStatusOffline;
|
||||
|
||||
/// No description provided for @primaryPortLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Primary Port'**
|
||||
String get primaryPortLabel;
|
||||
|
||||
/// No description provided for @listeningAddressesLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Listening Addresses:'**
|
||||
String get listeningAddressesLabel;
|
||||
|
||||
/// No description provided for @noListeningAddresses.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'None'**
|
||||
String get noListeningAddresses;
|
||||
|
||||
/// No description provided for @leaveNetworkConfirmationTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Leave Network?'**
|
||||
String get leaveNetworkConfirmationTitle;
|
||||
|
||||
/// No description provided for @leaveNetworkConfirmationText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Are you sure you want to leave network {networkId}?'**
|
||||
String leaveNetworkConfirmationText(String networkId);
|
||||
|
||||
/// No description provided for @confirmButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Confirm'**
|
||||
String get confirmButton;
|
||||
|
||||
/// No description provided for @cancelButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cancel'**
|
||||
String get cancelButton;
|
||||
|
||||
/// No description provided for @networkIdLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Network ID'**
|
||||
String get networkIdLabel;
|
||||
|
||||
/// No description provided for @networkIdHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enter 16-character Network ID'**
|
||||
String get networkIdHint;
|
||||
|
||||
/// No description provided for @invalidNetworkIdTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Invalid Network ID'**
|
||||
String get invalidNetworkIdTitle;
|
||||
|
||||
/// No description provided for @invalidNetworkIdText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Please enter a 16-character network ID.'**
|
||||
String get invalidNetworkIdText;
|
||||
|
||||
/// No description provided for @joinButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Join'**
|
||||
String get joinButton;
|
||||
|
||||
/// No description provided for @networksTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Networks'**
|
||||
String get networksTitle;
|
||||
|
||||
/// No description provided for @refreshNetworksTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Refresh Network List'**
|
||||
String get refreshNetworksTooltip;
|
||||
|
||||
/// No description provided for @noNetworksJoined.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No networks joined'**
|
||||
String get noNetworksJoined;
|
||||
|
||||
/// No description provided for @copiedToClipboard.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Copied {networkId} to clipboard!'**
|
||||
String copiedToClipboard(String networkId);
|
||||
|
||||
/// No description provided for @copyTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Copy'**
|
||||
String get copyTooltip;
|
||||
|
||||
/// No description provided for @leaveTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Leave'**
|
||||
String get leaveTooltip;
|
||||
|
||||
/// No description provided for @clearInputTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Clear input'**
|
||||
String get clearInputTooltip;
|
||||
|
||||
/// No description provided for @peersFeatureComingSoon.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Peers feature coming soon'**
|
||||
String get peersFeatureComingSoon;
|
||||
|
||||
/// No description provided for @noPeersFound.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No peers found'**
|
||||
String get noPeersFound;
|
||||
|
||||
/// No description provided for @navBarLabelStatus.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Status'**
|
||||
String get navBarLabelStatus;
|
||||
|
||||
/// No description provided for @navBarLabelNetworks.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Networks'**
|
||||
String get navBarLabelNetworks;
|
||||
|
||||
/// No description provided for @navBarLabelPeers.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Peers'**
|
||||
String get navBarLabelPeers;
|
||||
|
||||
/// No description provided for @appBarTitleStatus.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Status'**
|
||||
String get appBarTitleStatus;
|
||||
|
||||
/// No description provided for @appBarTitleNetworks.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Networks'**
|
||||
String get appBarTitleNetworks;
|
||||
|
||||
/// No description provided for @appBarTitlePeers.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Peers'**
|
||||
String get appBarTitlePeers;
|
||||
|
||||
/// No description provided for @joinNetworkSuccessText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Successfully joined network {networkId}!'**
|
||||
String joinNetworkSuccessText(String networkId);
|
||||
|
||||
/// No description provided for @joinNetworkErrorText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to join network: {error}'**
|
||||
String joinNetworkErrorText(String error);
|
||||
|
||||
/// No description provided for @leaveNetworkSuccessText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Successfully left network {networkId}.'**
|
||||
String leaveNetworkSuccessText(String networkId);
|
||||
|
||||
/// No description provided for @leaveNetworkErrorText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to leave network: {error}'**
|
||||
String leaveNetworkErrorText(String error);
|
||||
|
||||
/// No description provided for @refreshButtonLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Retry'**
|
||||
String get refreshButtonLabel;
|
||||
|
||||
/// No description provided for @loadPeersErrorText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load peers: {error}'**
|
||||
String loadPeersErrorText(String error);
|
||||
|
||||
/// No description provided for @loadNetworksErrorText.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load networks: {error}'**
|
||||
String loadNetworksErrorText(String error);
|
||||
|
||||
/// No description provided for @serviceNotRunning.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'ZeroTier service is not running'**
|
||||
String get serviceNotRunning;
|
||||
|
||||
/// No description provided for @moduleNotRunning.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'ZeroTier Magisk module is not running. Please check if you have installed the ZeroTier Magisk module.'**
|
||||
String get moduleNotRunning;
|
||||
|
||||
/// No description provided for @peerTunneled.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Relayed'**
|
||||
String get peerTunneled;
|
||||
|
||||
/// No description provided for @peerDirect.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Direct'**
|
||||
String get peerDirect;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
const _AppLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
Future<AppLocalizations> load(Locale locale) {
|
||||
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => <String>['en', 'zh'].contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
}
|
||||
|
||||
AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||
|
||||
|
||||
// Lookup logic when only language code is specified.
|
||||
switch (locale.languageCode) {
|
||||
case 'en': return AppLocalizationsEn();
|
||||
case 'zh': return AppLocalizationsZh();
|
||||
}
|
||||
|
||||
throw FlutterError(
|
||||
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.'
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for English (`en`).
|
||||
class AppLocalizationsEn extends AppLocalizations {
|
||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get statusRunning => 'Running';
|
||||
|
||||
@override
|
||||
String get statusStopped => 'Stopped';
|
||||
|
||||
@override
|
||||
String get refreshStatusTooltip => 'Refresh Status';
|
||||
|
||||
@override
|
||||
String get startButton => 'Start';
|
||||
|
||||
@override
|
||||
String get restartButton => 'Restart';
|
||||
|
||||
@override
|
||||
String get stopButton => 'Stop';
|
||||
|
||||
@override
|
||||
String get statusDetailsTitle => 'ZeroTier Details';
|
||||
|
||||
@override
|
||||
String get nodeAddressLabel => 'Node Address';
|
||||
|
||||
@override
|
||||
String get softwareVersionLabel => 'Software Version';
|
||||
|
||||
@override
|
||||
String get onlineStatusLabel => 'Online Status';
|
||||
|
||||
@override
|
||||
String get onlineStatusOnline => 'Online';
|
||||
|
||||
@override
|
||||
String get onlineStatusOffline => 'Offline';
|
||||
|
||||
@override
|
||||
String get primaryPortLabel => 'Primary Port';
|
||||
|
||||
@override
|
||||
String get listeningAddressesLabel => 'Listening Addresses:';
|
||||
|
||||
@override
|
||||
String get noListeningAddresses => 'None';
|
||||
|
||||
@override
|
||||
String get leaveNetworkConfirmationTitle => 'Leave Network?';
|
||||
|
||||
@override
|
||||
String leaveNetworkConfirmationText(String networkId) {
|
||||
return 'Are you sure you want to leave network $networkId?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get confirmButton => 'Confirm';
|
||||
|
||||
@override
|
||||
String get cancelButton => 'Cancel';
|
||||
|
||||
@override
|
||||
String get networkIdLabel => 'Network ID';
|
||||
|
||||
@override
|
||||
String get networkIdHint => 'Enter 16-character Network ID';
|
||||
|
||||
@override
|
||||
String get invalidNetworkIdTitle => 'Invalid Network ID';
|
||||
|
||||
@override
|
||||
String get invalidNetworkIdText => 'Please enter a 16-character network ID.';
|
||||
|
||||
@override
|
||||
String get joinButton => 'Join';
|
||||
|
||||
@override
|
||||
String get networksTitle => 'Networks';
|
||||
|
||||
@override
|
||||
String get refreshNetworksTooltip => 'Refresh Network List';
|
||||
|
||||
@override
|
||||
String get noNetworksJoined => 'No networks joined';
|
||||
|
||||
@override
|
||||
String copiedToClipboard(String networkId) {
|
||||
return 'Copied $networkId to clipboard!';
|
||||
}
|
||||
|
||||
@override
|
||||
String get copyTooltip => 'Copy';
|
||||
|
||||
@override
|
||||
String get leaveTooltip => 'Leave';
|
||||
|
||||
@override
|
||||
String get clearInputTooltip => 'Clear input';
|
||||
|
||||
@override
|
||||
String get peersFeatureComingSoon => 'Peers feature coming soon';
|
||||
|
||||
@override
|
||||
String get noPeersFound => 'No peers found';
|
||||
|
||||
@override
|
||||
String get navBarLabelStatus => 'Status';
|
||||
|
||||
@override
|
||||
String get navBarLabelNetworks => 'Networks';
|
||||
|
||||
@override
|
||||
String get navBarLabelPeers => 'Peers';
|
||||
|
||||
@override
|
||||
String get appBarTitleStatus => 'Status';
|
||||
|
||||
@override
|
||||
String get appBarTitleNetworks => 'Networks';
|
||||
|
||||
@override
|
||||
String get appBarTitlePeers => 'Peers';
|
||||
|
||||
@override
|
||||
String joinNetworkSuccessText(String networkId) {
|
||||
return 'Successfully joined network $networkId!';
|
||||
}
|
||||
|
||||
@override
|
||||
String joinNetworkErrorText(String error) {
|
||||
return 'Failed to join network: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String leaveNetworkSuccessText(String networkId) {
|
||||
return 'Successfully left network $networkId.';
|
||||
}
|
||||
|
||||
@override
|
||||
String leaveNetworkErrorText(String error) {
|
||||
return 'Failed to leave network: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get refreshButtonLabel => 'Retry';
|
||||
|
||||
@override
|
||||
String loadPeersErrorText(String error) {
|
||||
return 'Failed to load peers: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String loadNetworksErrorText(String error) {
|
||||
return 'Failed to load networks: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get serviceNotRunning => 'ZeroTier service is not running';
|
||||
|
||||
@override
|
||||
String get moduleNotRunning => 'ZeroTier Magisk module is not running. Please check if you have installed the ZeroTier Magisk module.';
|
||||
|
||||
@override
|
||||
String get peerTunneled => 'Relayed';
|
||||
|
||||
@override
|
||||
String get peerDirect => 'Direct';
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Chinese (`zh`).
|
||||
class AppLocalizationsZh extends AppLocalizations {
|
||||
AppLocalizationsZh([String locale = 'zh']) : super(locale);
|
||||
|
||||
@override
|
||||
String get statusRunning => '运行中';
|
||||
|
||||
@override
|
||||
String get statusStopped => '已停止';
|
||||
|
||||
@override
|
||||
String get refreshStatusTooltip => '刷新状态';
|
||||
|
||||
@override
|
||||
String get startButton => '启动';
|
||||
|
||||
@override
|
||||
String get restartButton => '重启';
|
||||
|
||||
@override
|
||||
String get stopButton => '停止';
|
||||
|
||||
@override
|
||||
String get statusDetailsTitle => 'ZeroTier 详细信息';
|
||||
|
||||
@override
|
||||
String get nodeAddressLabel => '节点地址';
|
||||
|
||||
@override
|
||||
String get softwareVersionLabel => '软件版本';
|
||||
|
||||
@override
|
||||
String get onlineStatusLabel => '在线状态';
|
||||
|
||||
@override
|
||||
String get onlineStatusOnline => '在线';
|
||||
|
||||
@override
|
||||
String get onlineStatusOffline => '离线';
|
||||
|
||||
@override
|
||||
String get primaryPortLabel => '主端口';
|
||||
|
||||
@override
|
||||
String get listeningAddressesLabel => '监听地址:';
|
||||
|
||||
@override
|
||||
String get noListeningAddresses => '无';
|
||||
|
||||
@override
|
||||
String get leaveNetworkConfirmationTitle => '离开网络?';
|
||||
|
||||
@override
|
||||
String leaveNetworkConfirmationText(String networkId) {
|
||||
return '您确定要离开网络 $networkId 吗?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get confirmButton => '确认';
|
||||
|
||||
@override
|
||||
String get cancelButton => '取消';
|
||||
|
||||
@override
|
||||
String get networkIdLabel => '网络 ID';
|
||||
|
||||
@override
|
||||
String get networkIdHint => '输入 16 位网络 ID';
|
||||
|
||||
@override
|
||||
String get invalidNetworkIdTitle => '无效的网络 ID';
|
||||
|
||||
@override
|
||||
String get invalidNetworkIdText => '请输入一个 16 位的网络 ID。';
|
||||
|
||||
@override
|
||||
String get joinButton => '加入';
|
||||
|
||||
@override
|
||||
String get networksTitle => '网络';
|
||||
|
||||
@override
|
||||
String get refreshNetworksTooltip => '刷新网络列表';
|
||||
|
||||
@override
|
||||
String get noNetworksJoined => '未加入任何网络';
|
||||
|
||||
@override
|
||||
String copiedToClipboard(String networkId) {
|
||||
return '已将 $networkId 复制到剪贴板!';
|
||||
}
|
||||
|
||||
@override
|
||||
String get copyTooltip => '复制';
|
||||
|
||||
@override
|
||||
String get leaveTooltip => '离开';
|
||||
|
||||
@override
|
||||
String get clearInputTooltip => '清除输入';
|
||||
|
||||
@override
|
||||
String get peersFeatureComingSoon => '节点功能即将推出';
|
||||
|
||||
@override
|
||||
String get noPeersFound => '未找到节点';
|
||||
|
||||
@override
|
||||
String get navBarLabelStatus => '状态';
|
||||
|
||||
@override
|
||||
String get navBarLabelNetworks => '网络';
|
||||
|
||||
@override
|
||||
String get navBarLabelPeers => '节点';
|
||||
|
||||
@override
|
||||
String get appBarTitleStatus => '状态';
|
||||
|
||||
@override
|
||||
String get appBarTitleNetworks => '网络';
|
||||
|
||||
@override
|
||||
String get appBarTitlePeers => '节点';
|
||||
|
||||
@override
|
||||
String joinNetworkSuccessText(String networkId) {
|
||||
return '成功加入网络 $networkId!';
|
||||
}
|
||||
|
||||
@override
|
||||
String joinNetworkErrorText(String error) {
|
||||
return '加入网络失败: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String leaveNetworkSuccessText(String networkId) {
|
||||
return '成功离开网络 $networkId。';
|
||||
}
|
||||
|
||||
@override
|
||||
String leaveNetworkErrorText(String error) {
|
||||
return '离开网络失败: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get refreshButtonLabel => '重试';
|
||||
|
||||
@override
|
||||
String loadPeersErrorText(String error) {
|
||||
return '加载节点列表失败: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String loadNetworksErrorText(String error) {
|
||||
return '加载网络列表失败: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get serviceNotRunning => 'ZeroTier服务未运行';
|
||||
|
||||
@override
|
||||
String get moduleNotRunning => 'ZeroTier Magisk模块未运行,请检查您是否安装Zerotier Magisk模块。';
|
||||
|
||||
@override
|
||||
String get peerTunneled => '中继';
|
||||
|
||||
@override
|
||||
String get peerDirect => '直连';
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"@@locale": "zh",
|
||||
"statusRunning": "运行中",
|
||||
"statusStopped": "已停止",
|
||||
"refreshStatusTooltip": "刷新状态",
|
||||
"startButton": "启动",
|
||||
"restartButton": "重启",
|
||||
"stopButton": "停止",
|
||||
"statusDetailsTitle": "ZeroTier 详细信息",
|
||||
"nodeAddressLabel": "节点地址",
|
||||
"softwareVersionLabel": "软件版本",
|
||||
"onlineStatusLabel": "在线状态",
|
||||
"onlineStatusOnline": "在线",
|
||||
"onlineStatusOffline": "离线",
|
||||
"primaryPortLabel": "主端口",
|
||||
"listeningAddressesLabel": "监听地址:",
|
||||
"noListeningAddresses": "无",
|
||||
|
||||
"leaveNetworkConfirmationTitle": "离开网络?",
|
||||
"leaveNetworkConfirmationText": "您确定要离开网络 {networkId} 吗?",
|
||||
"@leaveNetworkConfirmationText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"confirmButton": "确认",
|
||||
"cancelButton": "取消",
|
||||
"networkIdLabel": "网络 ID",
|
||||
"networkIdHint": "输入 16 位网络 ID",
|
||||
"invalidNetworkIdTitle": "无效的网络 ID",
|
||||
"invalidNetworkIdText": "请输入一个 16 位的网络 ID。",
|
||||
"joinButton": "加入",
|
||||
"networksTitle": "网络",
|
||||
"refreshNetworksTooltip": "刷新网络列表",
|
||||
"noNetworksJoined": "未加入任何网络",
|
||||
"copiedToClipboard": "已将 {networkId} 复制到剪贴板!",
|
||||
"@copiedToClipboard": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyTooltip": "复制",
|
||||
"leaveTooltip": "离开",
|
||||
"clearInputTooltip": "清除输入",
|
||||
"peersFeatureComingSoon": "节点功能即将推出",
|
||||
"noPeersFound": "未找到节点",
|
||||
|
||||
"navBarLabelStatus": "状态",
|
||||
"navBarLabelNetworks": "网络",
|
||||
"navBarLabelPeers": "节点",
|
||||
"appBarTitleStatus": "状态",
|
||||
"appBarTitleNetworks": "网络",
|
||||
"appBarTitlePeers": "节点",
|
||||
|
||||
"joinNetworkSuccessText": "成功加入网络 {networkId}!",
|
||||
"@joinNetworkSuccessText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"joinNetworkErrorText": "加入网络失败: {error}",
|
||||
"@joinNetworkErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "连接超时"
|
||||
}
|
||||
}
|
||||
},
|
||||
"leaveNetworkSuccessText": "成功离开网络 {networkId}。",
|
||||
"@leaveNetworkSuccessText": {
|
||||
"placeholders": {
|
||||
"networkId": {
|
||||
"type": "String",
|
||||
"example": "1234567890abcdef"
|
||||
}
|
||||
}
|
||||
},
|
||||
"leaveNetworkErrorText": "离开网络失败: {error}",
|
||||
"@leaveNetworkErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "权限不足"
|
||||
}
|
||||
}
|
||||
},
|
||||
"refreshButtonLabel": "重试",
|
||||
|
||||
"loadPeersErrorText": "加载节点列表失败: {error}",
|
||||
"@loadPeersErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "网络错误"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"loadNetworksErrorText": "加载网络列表失败: {error}",
|
||||
"@loadNetworksErrorText": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String",
|
||||
"example": "网络错误"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"serviceNotRunning": "ZeroTier服务未运行",
|
||||
|
||||
"moduleNotRunning": "ZeroTier Magisk模块未运行,请检查您是否安装Zerotier Magisk模块。",
|
||||
|
||||
"peerTunneled": "中继",
|
||||
"peerDirect": "直连"
|
||||
}
|
||||
Reference in New Issue
Block a user