Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ cat > /usr/share/nginx/html/config.json << EOF
}
EOF

# Inject OSRM_ENVIRONMENT into index.html meta tag to signal client to load config.json
if [ -f /usr/share/nginx/html/index.html ]; then
TMPFILE=$(mktemp)
awk -v env="$OSRM_ENVIRONMENT" '{
if ($0 ~ /<meta name="osrm-environment"/) {
sub(/content="[^"]*"/, "content=\"" env "\"")
}
print
}' /usr/share/nginx/html/index.html > "$TMPFILE" && mv "$TMPFILE" /usr/share/nginx/html/index.html || true
Comment on lines +64 to +69
fi

# Execute the default command (nginx) or any command passed to the container
if [ "$#" -eq 0 ]; then
exec nginx -g "daemon off;"
Expand Down
9 changes: 8 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<link rel='stylesheet' href="css/leaflet.css" />
<link rel="stylesheet" href="css/fonts.css" />
<link href='css/site.css' rel='stylesheet' />
<meta name="osrm-environment" content="">

</head>
<body>
Expand Down Expand Up @@ -59,7 +60,13 @@
});
}

loadConfig().then(loadBundle);
var envMeta = document.querySelector('meta[name="osrm-environment"]');
if (envMeta && envMeta.content === 'docker') {
loadConfig().then(loadBundle);
} else {
// Not running in Docker — skip fetching config.json to avoid noisy 404s
loadBundle();
}
})();
</script>
</body>
Expand Down
38 changes: 36 additions & 2 deletions src/leaflet_options.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,43 @@ function getZoom() {
return parsedZoom;
}

// Get language from config
// Get language, prefer browser settings when available; fallback to 'en'.
// Precedence (effective): URL param (handled in index.js) > browser language > 'en'
function getLanguage() {
return config.OSRM_LANGUAGE || 'en';
try {
if (typeof window !== 'undefined' && window.navigator) {
var nav = window.navigator;
var candidates = [];

if (Array.isArray(nav.languages)) {
Comment on lines +269 to +273
candidates = candidates.concat(nav.languages);
}
if (nav.language) candidates.push(nav.language);
if (nav.userLanguage) candidates.push(nav.userLanguage); // IE fallback

var localization = require('./localization');
for (var i = 0; i < candidates.length; i++) {
var lang = candidates[i];
if (!lang) continue;
lang = lang.trim();
// exact match (e.g., 'pt-BR')
if (localization.get(lang)) {
return lang;
}
// primary subtag match (e.g., 'en-US' -> 'en')
var short = lang.split('-')[0];
if (localization.get(short)) {
return short;
}
}
}
} catch (e) {
// Ignore detection errors and fall back to default
console.warn('Error detecting browser language:', e);
}

// Fallback to English when no browser language matches
return 'en';
}

// Get default layer from config
Expand Down
42 changes: 37 additions & 5 deletions test/leaflet_options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,20 +198,52 @@ describe('leaflet_options — runtime configuration overrides', () => {
});
});

describe('OSRM_LANGUAGE override', () => {
test('uses custom language when provided', () => {
global.window = { osrmConfig: { OSRM_LANGUAGE: 'de' } };
describe('language precedence (URL > browser > en)', () => {
test('uses browser language exact match', () => {
global.window = { navigator: { languages: ['de'], language: 'de' } };
const leafletOptions = require('../src/leaflet_options');
expect(leafletOptions.defaultState.language).toBe('de');
delete global.window;
});

test('defaults to en when language not provided', () => {
global.window = { osrmConfig: {} };
test('uses primary subtag when regional locale provided (en-US -> en)', () => {
global.window = { navigator: { languages: ['en-US'], language: 'en-US' } };
const leafletOptions = require('../src/leaflet_options');
expect(leafletOptions.defaultState.language).toBe('en');
delete global.window;
});
Comment on lines +209 to +228

test('prefers first candidate in navigator.languages array', () => {
global.window = { navigator: { languages: ['fr-CA', 'de'], language: 'fr-CA' } };
const leafletOptions = require('../src/leaflet_options');
expect(leafletOptions.defaultState.language).toBe('fr');
delete global.window;
});

test('matches exact regional variant when available (pt-BR)', () => {
global.window = { navigator: { languages: ['pt-BR'], language: 'pt-BR' } };
const leafletOptions = require('../src/leaflet_options');
expect(leafletOptions.defaultState.language).toBe('pt-BR');
delete global.window;
});

test('falls back to English when no supported browser languages', () => {
global.window = { navigator: { languages: ['xx','yy'], language: 'xx' } };
const leafletOptions = require('../src/leaflet_options');
expect(leafletOptions.defaultState.language).toBe('en');
delete global.window;
});

test('URL param (hl) takes precedence over browser default when merged', () => {
// Simulate browser default 'en' but URL param asks for 'de'
global.window = { navigator: { languages: ['en'], language: 'en' } };
const leafletOptions = require('../src/leaflet_options');
const links = require('../src/links');
const parsed = links.parse('hl=de');
const merged = Object.assign({}, leafletOptions.defaultState, parsed);
expect(merged.language).toBe('de');
delete global.window;
});
});
Comment on lines +201 to 268

describe('OSRM_LABEL and OSRM_DEFAULT_LAYER overrides', () => {
Expand Down
Loading