l10n: DMS coordinate directions

This commit is contained in:
Thibault Deckers 2021-11-02 10:52:51 +09:00
parent 4ee510d7a0
commit c74b94fb22
11 changed files with 69 additions and 30 deletions

View file

@ -176,6 +176,25 @@
"@coordinateFormatDms": {},
"coordinateFormatDecimal": "Decimal degrees",
"@coordinateFormatDecimal": {},
"coordinateDms": "{coordinate} {direction}",
"@coordinateDms": {
"placeholders": {
"coordinate": {
"type": "String"
},
"direction": {
"type": "String"
}
}
},
"coordinateDmsNorth": "N",
"@coordinateDmsNorth": {},
"coordinateDmsSouth": "S",
"@coordinateDmsSouth": {},
"coordinateDmsEast": "E",
"@coordinateDmsEast": {},
"coordinateDmsWest": "W",
"@coordinateDmsWest": {},
"unitSystemMetric": "Metric",
"@unitSystemMetric": {},

View file

@ -87,6 +87,11 @@
"coordinateFormatDms": "도분초",
"coordinateFormatDecimal": "소수점",
"coordinateDms": "{direction} {coordinate}",
"coordinateDmsNorth": "북위",
"coordinateDmsSouth": "남위",
"coordinateDmsEast": "동경",
"coordinateDmsWest": "서경",
"unitSystemMetric": "미터법",
"unitSystemImperial": "야드파운드법",

View file

@ -87,6 +87,11 @@
"coordinateFormatDms": "Градусы, минуты и секунды",
"coordinateFormatDecimal": "Десятичные градусы",
"coordinateDms": "{coordinate} {direction}",
"coordinateDmsNorth": "с. ш.",
"coordinateDmsSouth": "ю. ш.",
"coordinateDmsEast": "в. д.",
"coordinateDmsWest": "з. д.",
"unitSystemMetric": "Метрические",
"unitSystemImperial": "Имперские",

View file

@ -4,8 +4,10 @@ import 'package:aves/model/settings/enums.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/geo_utils.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';
@ -37,8 +39,9 @@ class CoordinateFilter extends CollectionFilter {
@override
EntryFilter get test => (entry) => GeoUtils.contains(sw, ne, entry.latLng);
String _formatBounds(CoordinateFormat format) {
String _formatBounds(AppLocalizations l10n, CoordinateFormat format) {
String s(LatLng latLng) => format.format(
l10n,
latLng,
minuteSecondPadding: minuteSecondPadding,
dmsSecondDecimals: 0,
@ -47,10 +50,10 @@ class CoordinateFilter extends CollectionFilter {
}
@override
String get universalLabel => _formatBounds(CoordinateFormat.decimal);
String get universalLabel => _formatBounds(lookupAppLocalizations(AppLocalizations.supportedLocales.first), CoordinateFormat.decimal);
@override
String getLabel(BuildContext context) => _formatBounds(context.read<Settings>().coordinateFormat);
String getLabel(BuildContext context) => _formatBounds(context.l10n, context.read<Settings>().coordinateFormat);
@override
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) => Icon(AIcons.geoBounds, size: size);

View file

@ -1,6 +1,7 @@
import 'package:aves/utils/geo_utils.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:latlong2/latlong.dart';
import 'enums.dart';
@ -15,12 +16,24 @@ extension ExtraCoordinateFormat on CoordinateFormat {
}
}
String format(LatLng latLng, {bool minuteSecondPadding = false, int dmsSecondDecimals = 2}) {
String format(AppLocalizations l10n, LatLng latLng, {bool minuteSecondPadding = false, int dmsSecondDecimals = 2}) {
switch (this) {
case CoordinateFormat.dms:
return GeoUtils.toDMS(latLng, minuteSecondPadding: minuteSecondPadding, secondDecimals: dmsSecondDecimals).join(', ');
return toDMS(l10n, latLng, minuteSecondPadding: minuteSecondPadding, secondDecimals: dmsSecondDecimals).join(', ');
case CoordinateFormat.decimal:
return [latLng.latitude, latLng.longitude].map((n) => n.toStringAsFixed(6)).join(', ');
}
}
// returns coordinates formatted as DMS, e.g. ['41° 24 12.2″ N', '2° 10 26.5″ E']
static List<String> toDMS(AppLocalizations l10n, LatLng latLng, {bool minuteSecondPadding = false, int secondDecimals = 2}) {
final lat = latLng.latitude;
final lng = latLng.longitude;
final latSexa = GeoUtils.decimal2sexagesimal(lat, minuteSecondPadding, secondDecimals);
final lngSexa = GeoUtils.decimal2sexagesimal(lng, minuteSecondPadding, secondDecimals);
return [
l10n.coordinateDms(latSexa, lat < 0 ? l10n.coordinateDmsSouth : l10n.coordinateDmsNorth),
l10n.coordinateDms(lngSexa, lng < 0 ? l10n.coordinateDmsWest : l10n.coordinateDmsEast),
];
}
}

View file

@ -5,7 +5,7 @@ import 'package:intl/intl.dart';
import 'package:latlong2/latlong.dart';
class GeoUtils {
static String _decimal2sexagesimal(final double degDecimal, final bool minuteSecondPadding, final int secondDecimals) {
static String decimal2sexagesimal(final double degDecimal, final bool minuteSecondPadding, final int secondDecimals) {
List<int> _split(final double value) {
// NumberFormat is necessary to create digit after comma if the value
// has no decimal point (only necessary for browser)
@ -32,16 +32,6 @@ class GeoUtils {
return '$deg° $minText $secText';
}
// returns coordinates formatted as DMS, e.g. ['41° 24 12.2″ N', '2° 10 26.5″ E']
static List<String> toDMS(LatLng latLng, {bool minuteSecondPadding = false, int secondDecimals = 2}) {
final lat = latLng.latitude;
final lng = latLng.longitude;
return [
'${_decimal2sexagesimal(lat, minuteSecondPadding, secondDecimals)} ${lat < 0 ? 'S' : 'N'}',
'${_decimal2sexagesimal(lng, minuteSecondPadding, secondDecimals)} ${lng < 0 ? 'W' : 'E'}',
];
}
static LatLng getLatLngCenter(List<LatLng> points) {
double x = 0;
double y = 0;

View file

@ -121,7 +121,7 @@ class _AddressRowState extends State<_AddressRow> {
? Constants.overlayUnknown
: entry.hasAddress
? entry.shortAddress
: settings.coordinateFormat.format(entry.latLng!));
: settings.coordinateFormat.format(context.l10n, entry.latLng!));
return Text(
location,
strutStyle: Constants.overflowStrutStyle,

View file

@ -23,6 +23,7 @@ class LanguageSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final currentCoordinateFormat = context.select<Settings, CoordinateFormat>((s) => s.coordinateFormat);
final currentUnitSystem = context.select<Settings, UnitSystem>((s) => s.unitSystem);
@ -34,13 +35,13 @@ class LanguageSection extends StatelessWidget {
icon: AIcons.language,
color: stringToColor('Language'),
),
title: context.l10n.settingsSectionLanguage,
title: l10n.settingsSectionLanguage,
expandedNotifier: expandedNotifier,
showHighlight: false,
children: [
const LocaleTile(),
ListTile(
title: Text(context.l10n.settingsCoordinateFormatTile),
title: Text(l10n.settingsCoordinateFormatTile),
subtitle: Text(currentCoordinateFormat.getName(context)),
onTap: () async {
final value = await showDialog<CoordinateFormat>(
@ -48,8 +49,8 @@ class LanguageSection extends StatelessWidget {
builder: (context) => AvesSelectionDialog<CoordinateFormat>(
initialValue: currentCoordinateFormat,
options: Map.fromEntries(CoordinateFormat.values.map((v) => MapEntry(v, v.getName(context)))),
optionSubtitleBuilder: (value) => value.format(Constants.pointNemo),
title: context.l10n.settingsCoordinateFormatTitle,
optionSubtitleBuilder: (value) => value.format(l10n, Constants.pointNemo),
title: l10n.settingsCoordinateFormatTitle,
),
);
if (value != null) {
@ -58,7 +59,7 @@ class LanguageSection extends StatelessWidget {
},
),
ListTile(
title: Text(context.l10n.settingsUnitSystemTile),
title: Text(l10n.settingsUnitSystemTile),
subtitle: Text(currentUnitSystem.getName(context)),
onTap: () async {
final value = await showDialog<UnitSystem>(
@ -66,7 +67,7 @@ class LanguageSection extends StatelessWidget {
builder: (context) => AvesSelectionDialog<UnitSystem>(
initialValue: currentUnitSystem,
options: Map.fromEntries(UnitSystem.values.map((v) => MapEntry(v, v.getName(context)))),
title: context.l10n.settingsUnitSystemTitle,
title: l10n.settingsUnitSystemTitle,
),
);
if (value != null) {

View file

@ -174,7 +174,7 @@ class _AddressInfoGroupState extends State<_AddressInfoGroup> {
final l10n = context.l10n;
return InfoRowGroup(
info: {
l10n.viewerInfoLabelCoordinates: settings.coordinateFormat.format(entry.latLng!),
l10n.viewerInfoLabelCoordinates: settings.coordinateFormat.format(l10n, entry.latLng!),
if (address.isNotEmpty) l10n.viewerInfoLabelAddress: address,
},
);

View file

@ -323,7 +323,7 @@ class _LocationRow extends AnimatedWidget {
@override
Widget build(BuildContext context) {
final location = entry.hasAddress ? entry.shortAddress : settings.coordinateFormat.format(entry.latLng!);
final location = entry.hasAddress ? entry.shortAddress : settings.coordinateFormat.format(context.l10n, entry.latLng!);
return Row(
children: [
const DecoratedIcon(AIcons.location, shadows: Constants.embossShadows, size: _iconSize),

View file

@ -1,14 +1,17 @@
import 'package:aves/model/settings/coordinate_format.dart';
import 'package:aves/utils/geo_utils.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:latlong2/latlong.dart';
import 'package:test/test.dart';
void main() {
test('Decimal degrees to DMS (sexagesimal)', () {
expect(GeoUtils.toDMS(LatLng(37.496667, 127.0275)), ['37° 29 48.00″ N', '127° 1 39.00″ E']); // Gangnam
expect(GeoUtils.toDMS(LatLng(78.9243503, 11.9230465)), ['78° 55 27.66″ N', '11° 55 22.97″ E']); // Ny-Ålesund
expect(GeoUtils.toDMS(LatLng(-38.6965891, 175.9830047)), ['38° 41 47.72″ S', '175° 58 58.82″ E']); // Taupo
expect(GeoUtils.toDMS(LatLng(-64.249391, -56.6556145)), ['64° 14 57.81″ S', '56° 39 20.21″ W']); // Marambio
expect(GeoUtils.toDMS(LatLng(0, 0)), ['0° 0 0.00″ N', '0° 0 0.00″ E']);
final l10n = lookupAppLocalizations(AppLocalizations.supportedLocales.first);
expect(ExtraCoordinateFormat.toDMS(l10n, LatLng(37.496667, 127.0275)), ['37° 29 48.00″ N', '127° 1 39.00″ E']); // Gangnam
expect(ExtraCoordinateFormat.toDMS(l10n, LatLng(78.9243503, 11.9230465)), ['78° 55 27.66″ N', '11° 55 22.97″ E']); // Ny-Ålesund
expect(ExtraCoordinateFormat.toDMS(l10n, LatLng(-38.6965891, 175.9830047)), ['38° 41 47.72″ S', '175° 58 58.82″ E']); // Taupo
expect(ExtraCoordinateFormat.toDMS(l10n, LatLng(-64.249391, -56.6556145)), ['64° 14 57.81″ S', '56° 39 20.21″ W']); // Marambio
expect(ExtraCoordinateFormat.toDMS(l10n, LatLng(0, 0)), ['0° 0 0.00″ N', '0° 0 0.00″ E']);
});
test('bounds center', () {