Merge branch 'main' into upstream/terrain-429-pause

This commit is contained in:
quanticsoul4772 authored and GitHub committed 2026-10-25 16:39:15 -07:00
commit 3acfcf94f5
9 files changed
+127 -13

No files matched your search

@@ -0,0 +1,4 @@
- Phrase slight and sharp ramps as directions, so a ramp reads "slightly left"
instead of "on the slightly left", and a lane names its side in both
the proxy response and localized browser instructions
(Rudy Celekli, @rudycelekli, #1343).
+4
View File
@@ -4150,6 +4150,10 @@ and as the last line of the list, because the arrival step is among the ones
dropped. A route of exactly 200 is complete, and a roundabout exit after the
200th keeps folding into it.
Directions ramp and exit text uses “on the left/right” only for a bare side;
slight and sharp modifiers read as “slightly/sharply left/right”. Lane instructions
name the left or right lane. The localized page and proxy English stay in sync.
Route duration labels select their unit after rounding seconds, switching to
minutes at 59.5 seconds; a 59.6-second leg displays as `1 min`, rather than `60 s`.
+43
View File
@@ -876,3 +876,46 @@ test('route numbers follow the page language and never break from their unit', (
const list = directionsStepList({ route });
assert.equal(list.items[1].lead, '240\u00a0м');
});
test('ramp and lane wording stays localized after choosing the maneuver form', (t) => {
t.after(() => setLocale('en'));
const cases = [
[
'ru',
'Въезжайте по съезду плавно налево на I-95',
'Сверните на съезд резко направо',
'Займите левую полосу',
],
[
'es',
'Toma la rampa ligeramente a la izquierda hacia I-95',
'Toma la salida bruscamente a la derecha',
'Toma el carril izquierdo',
],
[
'zh-CN',
'向左前方驶入匝道,进入 I-95',
'从出口向右后方驶出',
'使用左转车道',
],
];
for (const [locale, ramp, exit, lane] of cases) {
setLocale(locale);
assert.equal(
directionsInstruction({
type: 'on ramp',
modifier: 'slight left',
name: 'I-95',
}),
ramp,
);
assert.equal(
directionsInstruction({ type: 'off ramp', modifier: 'sharp right' }),
exit,
);
assert.equal(
directionsInstruction({ type: 'use lane', modifier: 'sharp left' }),
lane,
);
}
});
+25 -8
View File
@@ -54,6 +54,21 @@ function direction(modifier) {
return DIRECTION_WORDS[key] || key;
}
/**
* "on the left" only fits a bare side. "slight left" is the adverb
* "slightly left", and "on the slightly left" is not an instruction.
* @param {string} prefix "Take the ramp" or "Take the exit".
* @param {string} modifier OSRM maneuver modifier.
* @param {string} onto " onto …", or "".
*/
function directedWay(prefix, modifier, onto) {
const dir = direction(modifier);
if (dir === 'left' || dir === 'right')
return `${prefix} on the ${dir}${onto}`;
if (dir && dir !== 'straight') return `${prefix} ${dir}${onto}`;
return `${prefix}${onto}`;
}
function ordinal(n) {
if (!Number.isInteger(n) || n < 1) return null;
const suffix =
@@ -103,13 +118,9 @@ export function instructionFor(step) {
case 'merge':
return dir ? `Merge ${dir}${onto}` : `Merge${onto}`;
case 'on ramp':
return dir
? `Take the ramp on the ${dir}${onto}`
: `Take the ramp${onto}`;
return directedWay('Take the ramp', modifier, onto);
case 'off ramp':
return dir
? `Take the exit on the ${dir}${onto}`
: `Take the exit${onto}`;
return directedWay('Take the exit', modifier, onto);
case 'roundabout':
case 'rotary': {
const exit = ordinal(step?.exit);
@@ -124,8 +135,14 @@ export function instructionFor(step) {
case 'exit roundabout':
case 'exit rotary':
return `Exit the roundabout${onto}`;
case 'use lane':
return dir ? `Use the ${dir} lane${onto}` : `Continue${onto}`;
case 'use lane': {
const lane = modifier.includes('left')
? 'left'
: modifier.includes('right')
? 'right'
: '';
return lane ? `Use the ${lane} lane${onto}` : `Continue${onto}`;
}
case 'notification':
default:
return `Continue${onto}`;
+20
View File
@@ -77,6 +77,26 @@ test('instructions read like a navigator, one sentence per OSRM maneuver', () =>
instructionFor({ type: 'on ramp', modifier: 'left' }),
'Take the ramp on the left',
);
assert.equal(
instructionFor({ type: 'on ramp', modifier: 'slight left', name: 'I-95' }),
'Take the ramp slightly left onto I-95',
);
assert.equal(
instructionFor({ type: 'off ramp', modifier: 'sharp right', ref: 'I-280' }),
'Take the exit sharply right onto I-280',
);
assert.equal(
instructionFor({ type: 'on ramp', modifier: 'straight', name: 'US 101' }),
'Take the ramp onto US 101',
);
assert.equal(
instructionFor({ type: 'use lane', modifier: 'slight left' }),
'Use the left lane',
);
assert.equal(
instructionFor({ type: 'use lane', modifier: 'right', name: 'Main St' }),
'Use the right lane onto Main St',
);
assert.equal(
instructionFor({
type: 'merge',
+4
View File
@@ -1867,11 +1867,15 @@
"maneuver|Merge": "Incorpórate",
"Merge onto {road}": "Incorpórate a {road}",
"Take the ramp on the {direction}": "Toma la rampa {direction}",
"Take the ramp {direction}": "Toma la rampa {direction}",
"Take the ramp on the {direction} onto {road}": "Toma la rampa {direction} hacia {road}",
"Take the ramp {direction} onto {road}": "Toma la rampa {direction} hacia {road}",
"Take the ramp": "Toma la rampa",
"Take the ramp onto {road}": "Toma la rampa hacia {road}",
"Take the exit on the {direction}": "Toma la salida {direction}",
"Take the exit {direction}": "Toma la salida {direction}",
"Take the exit on the {direction} onto {road}": "Toma la salida {direction} hacia {road}",
"Take the exit {direction} onto {road}": "Toma la salida {direction} hacia {road}",
"Take the exit": "Toma la salida",
"Take the exit onto {road}": "Toma la salida hacia {road}",
"At the roundabout, take the {exit} exit": "En la rotonda, toma la {exit} salida",
+4
View File
@@ -1899,11 +1899,15 @@
"maneuver|Merge": "Перестройтесь",
"Merge onto {road}": "Въезжайте на {road}",
"Take the ramp on the {direction}": "Въезжайте на съезд {direction}",
"Take the ramp {direction}": "Въезжайте на съезд {direction}",
"Take the ramp on the {direction} onto {road}": "Въезжайте по съезду {direction} на {road}",
"Take the ramp {direction} onto {road}": "Въезжайте по съезду {direction} на {road}",
"Take the ramp": "Въезжайте на съезд",
"Take the ramp onto {road}": "Въезжайте по съезду на {road}",
"Take the exit on the {direction}": "Сверните на съезд {direction}",
"Take the exit {direction}": "Сверните на съезд {direction}",
"Take the exit on the {direction} onto {road}": "Сверните на съезд {direction} на {road}",
"Take the exit {direction} onto {road}": "Сверните на съезд {direction} на {road}",
"Take the exit": "Сверните на съезд",
"Take the exit onto {road}": "Сверните на съезд на {road}",
"At the roundabout, take the {exit} exit": "На кольце сверните на {exit} съезд",
+4
View File
@@ -626,11 +626,15 @@
"Merge onto {road}": "并入 {road}",
"maneuver|Merge": "并道",
"Take the ramp on the {direction} onto {road}": "{direction}驶入匝道,进入 {road}",
"Take the ramp {direction} onto {road}": "{direction}驶入匝道,进入 {road}",
"Take the ramp on the {direction}": "{direction}驶入匝道",
"Take the ramp {direction}": "{direction}驶入匝道",
"Take the ramp onto {road}": "驶入匝道,进入 {road}",
"Take the ramp": "驶入匝道",
"Take the exit on the {direction} onto {road}": "从出口{direction}驶出,进入 {road}",
"Take the exit {direction} onto {road}": "从出口{direction}驶出,进入 {road}",
"Take the exit on the {direction}": "从出口{direction}驶出",
"Take the exit {direction}": "从出口{direction}驶出",
"Take the exit onto {road}": "从出口驶出,进入 {road}",
"Take the exit": "从出口驶出",
"At the roundabout, take the {exit} exit onto {road}": "在环岛从{exit}出口驶出,进入 {road}",
+19 -5
View File
@@ -308,16 +308,24 @@ export function directionsInstruction(step) {
? t('Merge onto {road}', values)
: t('Merge', { context: 'maneuver' });
case 'on ramp':
if (direction)
if (modifier === 'left' || modifier === 'right')
return road
? t('Take the ramp on the {direction} onto {road}', values)
: t('Take the ramp on the {direction}', values);
if (direction && modifier !== 'straight')
return road
? t('Take the ramp {direction} onto {road}', values)
: t('Take the ramp {direction}', values);
return road ? t('Take the ramp onto {road}', values) : t('Take the ramp');
case 'off ramp':
if (direction)
if (modifier === 'left' || modifier === 'right')
return road
? t('Take the exit on the {direction} onto {road}', values)
: t('Take the exit on the {direction}', values);
if (direction && modifier !== 'straight')
return road
? t('Take the exit {direction} onto {road}', values)
: t('Take the exit {direction}', values);
return road ? t('Take the exit onto {road}', values) : t('Take the exit');
case 'roundabout':
case 'rotary':
@@ -346,9 +354,14 @@ export function directionsInstruction(step) {
return road
? t('Exit the roundabout onto {road}', values)
: t('Exit the roundabout');
case 'use lane':
if (direction) {
const lane = { road, direction: laneWord(modifier) };
case 'use lane': {
const side = modifier.includes('left')
? 'left'
: modifier.includes('right')
? 'right'
: '';
if (side) {
const lane = { road, direction: laneWord(side) };
return road
? t('Use the {direction} lane onto {road}', lane)
: t('Use the {direction} lane', lane);
@@ -356,6 +369,7 @@ export function directionsInstruction(step) {
return road
? t('Continue onto {road}', values)
: t('Continue', { context: 'maneuver' });
}
default:
return road
? t('Continue onto {road}', values)