Compare commits

..

7 Commits

Author SHA1 Message Date
Dennis Guse 92da9bd598 Release: v4.19.0 2025-03-16 11:15:50 +01:00
Dennis Guse 3df45c54d6 GPX: export TrackPointExtension correctly (order and rest of the data under <extension> directly).
Importing old (incorrect) and new (correct) format supported.

Part of #2074.
2025-03-16 11:06:21 +01:00
Dennis Guse c9f7ef810e GPX: export correct URL for Cluetrust.
Part of #2074.
2025-03-16 11:06:20 +01:00
Dennis Guse ebd4030869 GPX: correct URL for Cluetrust.
Part of #2074.
2025-03-16 08:59:37 +01:00
Dennis Guse 074484393e Bugfix: Markers without photo could not be deleted (created pre v4.18.0).
Introduced in 1b33184835

Fixes #2071.
2025-03-15 20:36:00 +01:00
Dennis Guse 08a231c64f README: added information for backups.
Fixes #2072.
2025-03-13 06:42:23 +01:00
Dennis Guse 07cbda5faa Translations: TA had invalid placeholders. 2025-03-08 18:12:21 +01:00
9 changed files with 249 additions and 33 deletions
+13
View File
@@ -153,6 +153,19 @@ slow and does not provide updates while recording.
The developer documentation is in [README_API.md](README_API.md).
## Backup
OpenTracks stores the data in the app-internal space:
`/data/data/de.dennisguse.opentracks[|.playstore]`
There is a SQLite database `database.db` that contains the tracks as well as the markers.
Pictures attached to markers are stored as separate files.
For backup and recovery, the best approach is to export as one KMZ file.
This will contain all the tracks, pictures and the data as similar as possible as stored internally.
In difference to backing up the database directly, a KMZ allows to be imported into a different (
e.g., newer) version of OpenTracks.
## Project history
_OpenTracks_ is based upon Google _My Tracks app_ ([code](https://code.google.com/archive/p/mytracks/)).
+2 -2
View File
@@ -46,8 +46,8 @@ android {
defaultConfig {
applicationId 'de.dennisguse.opentracks'
versionCode 6095
versionName "v4.18.0"
versionCode 6102
versionName "v4.19.0"
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
@@ -0,0 +1,7 @@
v4.19.0: OpenTracks
Changes:
- GPX export was not compliant (TrackPointExtension order and content)
Bugfix:
- pre-v4.18.0 markers without pictures could not be deleted
@@ -238,6 +238,81 @@ public class GPXTrackImporterTest {
), importedTrackPoints);
}
/**
* until v4.18.0: some extensions where incorrectly added to gpxtpx:TrackPointExtension
* We only need to check the trackpoints.
*/
@LargeTest
@Test
public void gpx_legacy_trackpointextension() throws IOException {
// given
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_gpx_trackpointextensions_incorrect);
// when
// 1. import
importTrackId = importer.importFile(inputStream).get(0);
// then: We only need to check the trackpoints.
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
TrackPointAssert a = new TrackPointAssert()
.setDelta(0.05); // speed is not fully
a.assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:02:03Z"),
3d, 14d, Distance.of(10),
Altitude.WGS84.of(10), null,
null,
Speed.of(15)))
.setAltitudeLoss(1f)
.setAltitudeGain(1f),
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:02:17Z"),
3d, 14.001, Distance.of(10),
Altitude.WGS84.of(10), null,
null,
Speed.of(5)))
.setAltitudeLoss(1f)
.setAltitudeGain(1f)
.setSensorDistance(Distance.of(12))
.setHeartRate(69)
.setPower(50f)
.setCadence(3f),
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:03:21Z"),
3d, 14.002, Distance.of(10),
Altitude.WGS84.of(10), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
.setAltitudeGain(0f),
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
new Position(
Instant.parse("2020-02-02T02:03:22Z"),
3d, 16d, Distance.of(10),
Altitude.WGS84.of(10), null,
null,
Speed.of(15)))
.setAltitudeLoss(0f)
.setAltitudeGain(0f),
new TrackPoint(TrackPoint.Type.TRACKPOINT,
new Position(
Instant.parse("2020-02-02T02:03:50Z"),
3d, 16.001, Distance.of(10),
Altitude.WGS84.of(10), null,
null,
Speed.of(10)))
.setAltitudeLoss(0f)
.setAltitudeGain(0f)
.setSpeed(Speed.of(15))
), actual);
}
@LargeTest
@Test
public void importExportTest_timezone() throws IOException {
+1 -1
View File
@@ -10,7 +10,7 @@ xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
xmlns:cluetrust="http://www.cluetrust.com/Schemas/"
xmlns:pwr="http://www.garmin.com/xmlschemas/PowerExtension/v1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 http://www.cluetrust.com/Schemas http://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
<wpt lat="3" lon="14">
<ele>10</ele>
<time>2021-01-07T21:51:59.179+01:15</time>
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<gpx
version="1.1"
creator="OpenTracks (Debug)"
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
xmlns:cluetrust="http://www.cluetrust.com/Schemas/"
xmlns:pwr="http://www.garmin.com/xmlschemas/PowerExtension/v1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
<wpt lat="3" lon="14">
<ele>10</ele>
<time>2020-02-02T03:02:03+01:00</time>
<name><![CDATA[Marker 1]]></name>
<desc><![CDATA[Marker 1 desc]]></desc>
<type><![CDATA[Marker 1 category]]></type>
</wpt>
<wpt lat="3" lon="14.001">
<ele>10</ele>
<time>2020-02-02T03:02:17+01:00</time>
<name><![CDATA[Marker 2]]></name>
<desc><![CDATA[Marker 2 desc]]></desc>
<type><![CDATA[Marker 2 category]]></type>
</wpt>
<trk>
<name><![CDATA[2020-02-02T03:02+01]]></name>
<desc><![CDATA[the description]]></desc>
<type><![CDATA[mountain biking]]></type>
<extensions>
<topografix:color>c0c0c0</topografix:color>
<opentracks:trackid>75c581d0-eef5-4aa2-91a3-66d2c6de4f6d</opentracks:trackid>
<opentracks:typeTranslated><![CDATA[the activity type]]></opentracks:typeTranslated>
<gpxtrkx:TrackStatsExtension>
<gpxtrkx:Distance>222125.53125</gpxtrkx:Distance>
<gpxtrkx:TimerTime>56</gpxtrkx:TimerTime>
<gpxtrkx:MovingTime>26</gpxtrkx:MovingTime>
<gpxtrkx:StoppedTime>30</gpxtrkx:StoppedTime>
<gpxtrkx:MaxSpeed>8543.2900390625</gpxtrkx:MaxSpeed>
<gpxtrkx:Ascent>2.0</gpxtrkx:Ascent>
<gpxtrkx:Descent>2.0</gpxtrkx:Descent>
</gpxtrkx:TrackStatsExtension>
</extensions>
<trkseg>
<trkpt lat="3" lon="14">
<ele>10</ele>
<time>2020-02-02T03:02:03+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>15</gpxtpx:speed>
<opentracks:gain>1</opentracks:gain>
<opentracks:loss>1</opentracks:loss>
<opentracks:accuracy_horizontal>10</opentracks:accuracy_horizontal></gpxtpx:TrackPointExtension></extensions>
</trkpt>
<trkpt lat="3" lon="14.001">
<ele>10</ele>
<time>2020-02-02T03:02:17+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>5</gpxtpx:speed>
<gpxtpx:hr>69</gpxtpx:hr>
<gpxtpx:cad>3</gpxtpx:cad>
<pwr:PowerInWatts>50</pwr:PowerInWatts>
<opentracks:gain>1</opentracks:gain>
<opentracks:loss>1</opentracks:loss>
<opentracks:accuracy_horizontal>10</opentracks:accuracy_horizontal><opentracks:distance>12</opentracks:distance>
<cluetrust:distance>12</cluetrust:distance>
</gpxtpx:TrackPointExtension></extensions>
</trkpt>
</trkseg>
<trkseg>
<trkpt lat="3" lon="14.002">
<ele>10</ele>
<time>2020-02-02T03:03:21+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>15</gpxtpx:speed>
<opentracks:gain>0</opentracks:gain>
<opentracks:loss>0</opentracks:loss>
<opentracks:accuracy_horizontal>10</opentracks:accuracy_horizontal></gpxtpx:TrackPointExtension></extensions>
</trkpt>
</trkseg>
<trkseg>
<trkpt lat="3" lon="16">
<ele>10</ele>
<time>2020-02-02T03:03:22+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>15</gpxtpx:speed>
<opentracks:gain>0</opentracks:gain>
<opentracks:loss>0</opentracks:loss>
<opentracks:accuracy_horizontal>10</opentracks:accuracy_horizontal></gpxtpx:TrackPointExtension></extensions>
</trkpt>
<trkpt lat="3" lon="16.001">
<ele>10</ele>
<time>2020-02-02T03:03:50+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>15</gpxtpx:speed>
<opentracks:gain>0</opentracks:gain>
<opentracks:loss>0</opentracks:loss>
<opentracks:accuracy_horizontal>10</opentracks:accuracy_horizontal></gpxtpx:TrackPointExtension></extensions>
</trkpt>
</trkseg>
</trk>
</gpx>
@@ -434,7 +434,14 @@ public class ContentProviderUtils {
marker.setIcon(cursor.getString(iconIndex));
}
if (!cursor.isNull(photoUrlIndex)) {
marker.setPhotoUrl(Uri.parse(cursor.getString(photoUrlIndex)));
String photoUrl = cursor.getString(photoUrlIndex);
if (photoUrl.isEmpty()) {
// Before v4.18.0: a marker without a picture as URL ""
// TODO Data should be migrated.
marker.setPhotoUrl(null);
} else {
marker.setPhotoUrl(Uri.parse(cursor.getString(photoUrlIndex)));
}
}
@@ -229,7 +229,7 @@ public class GPXTrackExporter implements TrackExporter {
+ " http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd"
+ " http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd"
+ " http://www.garmin.com/xmlschemas/TrackStatsExtension/v1"
+ " http://www.cluetrust.com/Schemas http://www.cluetrust.com/Schemas/gpxdata10.xsd"
+ " http://www.cluetrust.com/Schemas https://www.cluetrust.com/Schemas/gpxdata10.xsd"
+ " http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd\">");
}
@@ -321,51 +321,62 @@ public class GPXTrackExporter implements TrackExporter {
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(trackPoint.getTime(), zoneOffset) + "</time>");
{
String trackPointExtensionContent = "";
if (trackPoint.hasSpeed()) {
trackPointExtensionContent += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.getSpeed().toMPS()) + "</gpxtpx:speed>\n";
}
String trackPointExtensionV2Content = "";
if (trackPoint.hasHeartRate()) {
trackPointExtensionContent += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.getHeartRate().getBPM()) + "</gpxtpx:hr>\n";
trackPointExtensionV2Content += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.getHeartRate().getBPM()) + "</gpxtpx:hr>\n";
}
if (trackPoint.hasCadence()) {
trackPointExtensionContent += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.getCadence().getRPM()) + "</gpxtpx:cad>\n";
trackPointExtensionV2Content += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.getCadence().getRPM()) + "</gpxtpx:cad>\n";
}
if (trackPoint.hasSpeed()) {
trackPointExtensionV2Content += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.getSpeed().toMPS()) + "</gpxtpx:speed>\n";
}
String extensionContent = "";
if (trackPoint.hasPower()) {
trackPointExtensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
extensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
}
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGain() ? (double) tp.getAltitudeGain() : null);
if (cumulativeGain != null) {
trackPointExtensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
extensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
}
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeLoss() ? (double) tp.getAltitudeLoss() : null);
if (cumulativeLoss != null) {
trackPointExtensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
extensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
}
if (trackPoint.hasHorizontalAccuracy()) {
trackPointExtensionContent += ("<opentracks:accuracy_horizontal>" + DISTANCE_FORMAT.format(trackPoint.getHorizontalAccuracy().toM()) + "</opentracks:accuracy_horizontal>");
extensionContent += ("<opentracks:accuracy_horizontal>" + DISTANCE_FORMAT.format(trackPoint.getHorizontalAccuracy().toM()) + "</opentracks:accuracy_horizontal>");
}
if (trackPoint.hasVerticalAccuracy()) {
trackPointExtensionContent += ("<opentracks:accuracy_vertical>" + DISTANCE_FORMAT.format(trackPoint.getVerticalAccuracy().toM()) + "</opentracks:accuracy_vertical>");
extensionContent += ("<opentracks:accuracy_vertical>" + DISTANCE_FORMAT.format(trackPoint.getVerticalAccuracy().toM()) + "</opentracks:accuracy_vertical>");
}
cumulativeDistance = Distance.ofOrNull(cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasSensorDistance() ? tp.getSensorDistance().toM() : null));
if (cumulativeDistance != null) {
trackPointExtensionContent += ("<opentracks:distance>" + DISTANCE_FORMAT.format(cumulativeDistance.toM()) + "</opentracks:distance>\n");
trackPointExtensionContent += ("<cluetrust:distance>" + DISTANCE_FORMAT.format(trackDistance.plus(cumulativeDistance).toM()) + "</cluetrust:distance>\n");
extensionContent += ("<opentracks:distance>" + DISTANCE_FORMAT.format(cumulativeDistance.toM()) + "</opentracks:distance>\n");
extensionContent += ("<cluetrust:distance>" + DISTANCE_FORMAT.format(trackDistance.plus(cumulativeDistance).toM()) + "</cluetrust:distance>\n");
}
if (!trackPointExtensionContent.isEmpty()) {
printWriter.println("<extensions><gpxtpx:TrackPointExtension>");
printWriter.print(trackPointExtensionContent);
printWriter.println("</gpxtpx:TrackPointExtension></extensions>");
if (!extensionContent.isEmpty() || !trackPointExtensionV2Content.isEmpty()) {
printWriter.println("<extensions>");
if (!trackPointExtensionV2Content.isEmpty()) {
printWriter.println("<gpxtpx:TrackPointExtension>");
printWriter.print(trackPointExtensionV2Content);
printWriter.println("</gpxtpx:TrackPointExtension>");
}
if (!extensionContent.isEmpty()) {
printWriter.print(extensionContent);
}
printWriter.println("</extensions>");
}
}
+10 -10
View File
@@ -110,16 +110,16 @@
<string name="activity_type_workout">பயிற்சி</string>
<string name="description_activity_type">செயல்பாட்டு வகை: %1$s</string>
<string name="description_average_moving_pace_in_minute">சராசரி நகரும் வேகம்: %1$s min/km ( %2$s min/mi)</string>
<string name="description_average_moving_speed">சராசரி நகரும் வேகம்: %1 $ .2f கிமீ/மணி ( %2 $ .1f மைல்/எச்)</string>
<string name="description_average_moving_speed">சராசரி நகரும் வேகம்: %1$.2f கிமீ/மணி ( %2$.1f மைல்/எச்)</string>
<string name="description_average_pace_in_minute">சராசரி வேகம்: %1$s min/km ( %2$s min/mi)</string>
<string name="description_average_speed">சராசரி வேகம்: %1 $ .2f கிமீ/மணி ( %2 $ .1f Mi/h)</string>
<string name="description_average_speed">சராசரி வேகம்: %1$.2f கிமீ/மணி ( %2$.1f Mi/h)</string>
<string name="description_altitude_gain">உயர்வு ஆதாயம்: %1$d மீ ( %2$d அடி)</string>
<string name="description_altitude_loss">உயர இழப்பு: %1$d மீ ( %2$d அடி)</string>
<string name="description_altitude_imperial">உயரம் (அடி)</string>
<string name="description_altitude_metric">உயரம் (மீ)</string>
<string name="description_fastest_pace_in_minute">வேகமான வேகம்: %1$s min/km ( %2$s min/mi)</string>
<string name="description_max_altitude">அதிகபட்ச உயர்வு: %1$d மீ ( %2$d அடி)</string>
<string name="description_max_speed">அதிகபட்ச வேகம்: %1 $ .2f கிமீ/மணி ( %2 $ .1f Mi/h)</string>
<string name="description_max_speed">அதிகபட்ச வேகம்: %1$.2f கிமீ/மணி ( %2$.1f Mi/h)</string>
<string name="description_moving_time">நகரும் நேரம்: %1$s</string>
<string name="description_pace_imperial">விரைவு (நிமிடம்/மை)</string>
<string name="description_pace_nautical">விரைவு (நிமிடம்/என்.எம்)</string>
@@ -134,7 +134,7 @@
<string name="description_speed_nautical">விரைவு (முடிச்சுகள்)</string>
<string name="description_speed_metric">விரைவு (கிமீ/மணிநேரம்)</string>
<string name="description_time">நேரம்</string>
<string name="description_total_distance">மொத்த தூரம்: %1 $ .2f கி.மீ ( %2 $ .1f மை)</string>
<string name="description_total_distance">மொத்த தூரம்: %1$.2f கி.மீ ( %2$.1f மை)</string>
<string name="description_total_time">மொத்த நேரம்: %1$s</string>
<string name="description_speed_source_gps">உலக இடம் காட்டும் அமைப்பு</string>
<string name="export_with_photos">புகைப்படங்களுடன்</string>
@@ -251,7 +251,7 @@
<string name="sensor_state_power_avg">ஏ.வி.சி ஆற்றல்</string>
<string name="sensor_state_power_max">அதிகபட்ச ஆற்றல்</string>
<string name="sensor_state_power_unit">W</string>
<string name="sensor_could_not_scan">ஊடலை சாதனங்களுக்கு ச்கேன் செய்ய முடியவில்லை (பிழை %1 $ i).</string>
<string name="sensor_could_not_scan">ஊடலை சாதனங்களுக்கு ச்கேன் செய்ய முடியவில்லை (பிழை %1$i).</string>
<string name="bluetooth_disabled">ப்ளூடூத்தை இயக்கவும்.</string>
<string name="bluetooth_sensor_summary">%1$s (%2$s)</string>
<string name="settings_defaults_title">இயல்புநிலை அலகுகள் மற்றும் செயல்பாடு</string>
@@ -394,16 +394,16 @@
<string name="location_latitude_longitude">%1$s, %2$s</string>
<string name="value_integer_feet_recommended">%1$d அடி (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_integer_kilometer_hour">%1$d கிமீ/மணி</string>
<string name="value_float_kilometer_hour">%1 $ .1f கிமீ/மணி</string>
<string name="value_float_kilometer_hour">%1$.1f கிமீ/மணி</string>
<string name="value_integer_meter_excellent_gps">%1$d மீ (சிறந்த சி.பி.எச்)</string>
<string name="value_integer_meter_poor_gps">%1$d மீ (மோசமான சி.பி.எச்)</string>
<string name="value_integer_meter_recommended">%1$d மீ (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_integer_mile_hour">%1$d Mi/h</string>
<string name="value_integer_knots">%1$d முடிச்சுகள்</string>
<string name="value_float_mile_hour">%1 $ .1f Mi/h</string>
<string name="value_float_knots">%1 $ .1f முடிச்சுகள்</string>
<string name="value_float_mile_hour_recommended">%1 $ .1f Mi/h (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_float_knots_recommended">%1 $ .1f முடிச்சுகள் (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_float_mile_hour">%1$.1f Mi/h</string>
<string name="value_float_knots">%1$.1f முடிச்சுகள்</string>
<string name="value_float_mile_hour_recommended">%1$.1f Mi/h (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_float_knots_recommended">%1$.1f முடிச்சுகள் (பரிந்துரைக்கப்படுகிறது)</string>
<string name="value_integer_second">%1$d கள்</string>
<string name="value_none">எதுவுமில்லை</string>
<string name="value_off">அணை</string>