diff --git a/package-lock.json b/package-lock.json index b7dcaff..9b1f9e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "tailwindcss": "^4.1.17", "tailwindcss-animate": "^1.0.7", "vue": "^3.5.25", + "vue-i18n": "^11.2.2", "vue-router": "^4.6.3" }, "devDependencies": { @@ -719,6 +720,47 @@ "@swc/helpers": "^0.5.0" } }, + "node_modules/@intlify/core-base": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.2.2.tgz", + "integrity": "sha512-0mCTBOLKIqFUP3BzwuFW23hYEl9g/wby6uY//AC5hTgQfTsM2srCYF2/hYGp+a5DZ/HIFIgKkLJMzXTt30r0JQ==", + "dependencies": { + "@intlify/message-compiler": "11.2.2", + "@intlify/shared": "11.2.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.2.2.tgz", + "integrity": "sha512-XS2p8Ff5JxWsKhgfld4/MRQzZRQ85drMMPhb7Co6Be4ZOgqJX1DzcZt0IFgGTycgqL8rkYNwgnD443Q+TapOoA==", + "dependencies": { + "@intlify/shared": "11.2.2", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.2.2.tgz", + "integrity": "sha512-OtCmyFpSXxNu/oET/aN6HtPCbZ01btXVd0f3w00YsHOb13Kverk1jzA2k47pAekM55qbUw421fvPF1yxZ+gicw==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -3178,6 +3220,25 @@ "eslint": "^8.57.0 || ^9.0.0" } }, + "node_modules/vue-i18n": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.2.2.tgz", + "integrity": "sha512-ULIKZyRluUPRCZmihVgUvpq8hJTtOqnbGZuv4Lz+byEKZq4mU0g92og414l6f/4ju+L5mORsiUuEPYrAuX2NJg==", + "dependencies": { + "@intlify/core-base": "11.2.2", + "@intlify/shared": "11.2.2", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vue-router": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", diff --git a/package.json b/package.json index c60b902..00eb39d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "tailwindcss": "^4.1.17", "tailwindcss-animate": "^1.0.7", "vue": "^3.5.25", + "vue-i18n": "^11.2.2", "vue-router": "^4.6.3" }, "devDependencies": { diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue index 74f1056..9abfc64 100644 --- a/src/components/AppFooter.vue +++ b/src/components/AppFooter.vue @@ -79,7 +79,7 @@ import { RouterLink } from 'vue-router' rel="noopener noreferrer" class="text-xs text-orange-600 hover:text-orange-700 underline-offset-2 hover:underline dark:text-orange-400 dark:hover:text-orange-300" > - Support on Patreon + {{ $t("message.footer.support_on_patreon") }} @@ -93,7 +93,7 @@ import { RouterLink } from 'vue-router' to="/about" class="text-neutral-700 hover:text-beammp-blue transition-colors dark:text-neutral-500 dark:hover:text-blue-400" > - About + {{ $t("message.footer.about") }} · - Privacy Policy + {{ $t("message.footer.privacy_policy") }} · - Terms & Conditions + {{ $t("message.footer.terms_conditions") }} diff --git a/src/components/AppNavigation.vue b/src/components/AppNavigation.vue index 8de46d1..bf30d86 100644 --- a/src/components/AppNavigation.vue +++ b/src/components/AppNavigation.vue @@ -54,7 +54,7 @@ function closeMobileMenu() { rel="noopener noreferrer" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Forum + {{ $t('message.nav.forums') }} @@ -66,7 +66,7 @@ function closeMobileMenu() { rel="noopener noreferrer" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Docs + {{ $t('message.nav.docs') }} @@ -76,7 +76,7 @@ function closeMobileMenu() { to="/communities" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Communities + {{ $t('message.nav.communities') }} @@ -86,7 +86,7 @@ function closeMobileMenu() { to="/servers" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Servers + {{ $t('message.nav.servers') }} @@ -96,7 +96,7 @@ function closeMobileMenu() { to="/stats" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Statistics + {{ $t('message.nav.statistics') }} @@ -108,7 +108,7 @@ function closeMobileMenu() { rel="noopener noreferrer" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - GitHub + {{ $t('message.nav.github') }} @@ -120,7 +120,7 @@ function closeMobileMenu() { rel="noopener noreferrer" :class="cn(navigationMenuTriggerStyle(), 'bg-transparent text-neutral-900 hover:bg-neutral-100 hover:text-neutral-900 dark:bg-transparent dark:text-white dark:hover:bg-neutral-800 dark:hover:text-white')" > - Patreon + {{ $t('message.nav.patreon') }} @@ -157,13 +157,6 @@ function closeMobileMenu() { class="md:hidden border-t border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900" >
- - About - - Forum + {{ $t('message.nav.forums') }} - Docs + {{ $t('message.nav.docs') }} - Communities + {{ $t('message.nav.communities') }} - Servers + {{ $t('message.nav.servers') }} - Statistics + {{ $t('message.nav.statistics') }} - GitHub + {{ $t('message.nav.github') }} - Patreon + {{ $t('message.nav.patreon') }}
diff --git a/src/components/ThemeToggle.vue b/src/components/ThemeToggle.vue index b6ea336..0a470ad 100644 --- a/src/components/ThemeToggle.vue +++ b/src/components/ThemeToggle.vue @@ -45,7 +45,7 @@ onMounted(() => { ? 'bg-white shadow-sm text-neutral-900 dark:bg-neutral-700 dark:text-white' : 'text-neutral-600 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-200', ]" - title="Light mode" + :title="$t('message.theme.light')" @click="setTheme('light')" > @@ -57,7 +57,7 @@ onMounted(() => { ? 'bg-white shadow-sm text-neutral-900 dark:bg-neutral-700 dark:text-white' : 'text-neutral-600 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-200', ]" - title="System theme" + :title="$t('message.theme.system')" @click="setTheme('system')" > @@ -69,7 +69,7 @@ onMounted(() => { ? 'bg-white shadow-sm text-neutral-900 dark:bg-neutral-700 dark:text-white' : 'text-neutral-600 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-200', ]" - title="Dark mode" + :title="$t('message.theme.dark')" @click="setTheme('dark')" > diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 0000000..5d01021 --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,38 @@ +import { nextTick } from 'vue' +import { createI18n } from 'vue-i18n' + +export const SUPPORT_LOCALES = ['en'] + +export function setupI18n(options = { locale: 'en' }) { + const i18n = createI18n(options) + setI18nLanguage(i18n, options.locale) + return i18n +} + +export function setI18nLanguage(i18n, locale) { + if (i18n.mode === 'legacy') { + i18n.global.locale = locale + } else { + i18n.global.locale.value = locale + } + /** + * NOTE: + * If you need to specify the language setting for headers, such as the `fetch` API, set it here. + * The following is an example for axios. + * + * axios.defaults.headers.common['Accept-Language'] = locale + */ + document.querySelector('html').setAttribute('lang', locale) +} + +export async function loadLocaleMessages(i18n, locale) { + // load locale messages with dynamic import + const messages = await import( + /* webpackChunkName: "locale-[request]" */ `./locales/${locale}.json` + ) + + // set locale and locale message + i18n.global.setLocaleMessage(locale, messages.default) + + return nextTick() +} diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..2365b1d --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,514 @@ +{ + "message": { + "theme": { + "light": "Light mode", + "dark": "Dark mode", + "system": "System" + }, + "nav": { + "home": "Home", + "forums": "Forums", + "docs": "Docs", + "communities": "Communities", + "servers": "Servers", + "statistics": "Statistics", + "github": "GitHub", + "patreon": "Patreon", + "theme": { + "light": "Light Theme", + "dark": "Dark Theme", + "system": "System Theme" + } + }, + "footer": { + "support_on_patreon": "Support us on Patreon", + "about": "About", + "privacy_policy": "Privacy Policy", + "terms_conditions": "Terms & Conditions" + }, + "404": { + "title": "Page Not Found", + "description": "The page you requested doesn’t exist. It may have been moved or removed.", + "return_home": "Return Home" + }, + "home": { + "hero": { + "title": "Multiplayer for BeamNG.Drive", + "subtitle": "Experience the ultimate soft-body physics with friends. Race, roleplay, or just cruise together.", + "download_now": "Download Now", + "browse_servers": "Browse Servers" + }, + "metrics": { + "active_players": "Active Players", + "players_online": "Players Online", + "public_servers": "Public Servers", + "all_servers": "All Servers" + }, + "why_choose_beammp": "Why Choose BeamMP?", + "features": { + "stable_servers": { + "title": "Stable Servers", + "description": "BeamMP allows for stable servers, with a variety of servers located across the globe." + }, + "beamng": { + "title": "BeamNG.drive", + "description": "BeamMP uses the same maps, vehicles & mods so you don't need to learn anything new!" + }, + "standalone": { + "title": "Standalone", + "description": "BeamMP doesn't modify your original installation, so you can play either singleplayer or multiplayer." + }, + "sync": { + "title": "Sync Quality", + "description": "BeamMP updates your vehicle position ~100 times per second, allowing for a smooth overall experience." + } + }, + "communities": { + "join": "Join a Thriving Community", + "description": "Discover diverse gameplay experiences across hundreds of unique servers", + "racing": { + "name": "Racing Communities", + "description": "Competitive racing leagues and time trials with players worldwide" + }, + "roleplay": { + "name": "Roleplay Servers", + "description": "Immersive roleplay experiences from police chases to delivery services" + }, + "crash": { + "name": "Crash & Derby", + "description": "Demolition derbies and destruction-focused gameplay modes" + }, + "freeroam": { + "name": "Freeroam", + "description": "Casual multiplayer sessions exploring maps with friends" + } + }, + "find": { + "title": "Find Your Perfect Server", + "description": "Browse hundreds of active servers with different game modes, mods, and communities. From competitive racing to casual free roam, there's something for everyone.", + "points": { + "custom": "Custom Game Modes", + "custom_desc": "Unique experiences created by the community", + "moderation": "Active Moderation", + "moderation_desc": "Safe and friendly gaming environment", + "global": "Global Network", + "global_desc": "Servers located worldwide for low latency" + }, + "browse_all_servers": "Browse All Servers" + }, + "devFeatures": { + "title": "Built for Developers", + "description": "Create custom game modes, host your own server, and contribute to the project", + "lua": { + "title": "Lua API", + "description": "Powerful server-side Lua scripting for custom game modes and features" + }, + "docs": { + "title": "Documentation", + "description": "Comprehensive guides and API references for server development" + }, + "openSource": { + "title": "Open Source", + "description": "Community-driven development with source available on GitHub" + }, + "learn_more": "Learn More", + "host": { + "title": "Ready to Host Your Own Server?", + "description": "Download the server files and create your own unique BeamMP experience", + "windows": "Windows Server", + "linux": "Linux Builds" + } + }, + "faq": { + "title": "Frequently Asked Questions", + "0": { + "question": "The server list is not showing up!", + "answer": + "Try restarting BeamMP as this can sometimes happen. If this fails to fix your issue please create a topic on our forum or visit the support channel on our discord." + }, + "1": { + "question": "How do I open a ticket in case something doesn't work or I have questions?", + "answer": + "Please check the #how-to-use channel in Discord and on our forum. Please give an accurate description of what you have done so the support team will help you in a fast and effective way." + }, + "2": { + "question": "Help! I'm getting error codes", + "answer": + "Please head over to our forum and see if anyone has had the issue before. It is likely that someone else has at some point and therefore there will also probably be a solution posted with it too in the replies. Alternatively visit our discord where the larger portion of community is currently based." + }, + "3": { + "question": "Does this work with pirated versions of BeamNG.drive?", + "answer": + "We don't know if it works with pirated versions of BeamNG.drive, but we will not provide any support to non legit copies of the game. Nor will we change to support it." + }, + "4": { + "question": "How do I host a server?", + "answer": + "The server files required for hosting your own server can be found at the top of this page below the client download. You will also require an authentication key which can be found from keymaster. Further information around the setup can be found on our wiki." + }, + "5": { + "question": "Can I use mods?", + "answer": + "Mods are supported. These are installed on the server. See our wiki for more information." + } + }, + "stats": { + "active_players": "Active Players", + "global_servers": "Global Servers", + "total_downloads": "Total Downloads" + } + }, + "communities": { + "title": "Communities", + "description": "Discover thriving communities built around BeamMP. From competitive racing leagues to casual free roam sessions, find your perfect group to play with.", + "starting": { + "title": "Want to Start Your Own Community?", + "description": "Host your own BeamMP server and build a community around your favorite game modes", + "setup_guide": "Server Setup Guide", + "join_discord": "Join Our Discord" + } + }, + "servers": { + "title": "Servers", + "description": "Browse and join BeamMP servers from around the world. Find your favorite game modes, communities, and experiences all in one place.", + "show_only": "Show Only:", + "loading_servers": "Loading servers...", + "server_count": "0 servers found | 1 server found | {count} servers found", + "players_found": "0 players | 1 player | {count} players", + "filters": { + "hide_empty": "Hide Empty", + "hide_full": "Hide Full", + "search": "Search Servers...", + "hide_password": "Hide Password Protected", + "show_official": "Official", + "show_partner": "Partner", + "show_featured": "Featured" + }, + "table_headers": { + "location": "Location", + "name": "Server Name", + "map": "Map", + "players": "Players", + "mods": "Mods", + "status": "Status" + } + }, + "statistics": { + "title": "Statistics", + "description": "Live snapshot metrics from active servers and a player volume timeline. Releases can be annotated on the chart.", + "loading": "Loading…", + "peak": "Peak: {count}", + "current_players": "Current Players", + "current_servers": "Current Servers", + "avg_players_per_server": "AVG Players / Server", + "official_servers": "Official Servers", + "partner_servers": "Partner Servers", + "player_volume": "Player Volume Over Time", + "hint": "Release markers are shown as orange vertical lines (e.g., v3.0.0, v4.0.0). Hover over data points for details.", + "server_volume": "Server Volume Over Time", + "server_hint": "Server count follows similar trends. Release markers indicate major version launches." + }, + "countries_iso": { + "AF": "Afghanistan", + "AX": "Aland Islands", + "AL": "Albania", + "DZ": "Algeria", + "AS": "American Samoa", + "AD": "Andorra", + "AO": "Angola", + "AI": "Anguilla", + "AQ": "Antarctica", + "AG": "Antigua And Barbuda", + "AR": "Argentina", + "AM": "Armenia", + "AW": "Aruba", + "AU": "Australia", + "AT": "Austria", + "AZ": "Azerbaijan", + "BS": "Bahamas", + "BH": "Bahrain", + "BD": "Bangladesh", + "BB": "Barbados", + "BY": "Belarus", + "BE": "Belgium", + "BZ": "Belize", + "BJ": "Benin", + "BM": "Bermuda", + "BT": "Bhutan", + "BO": "Bolivia", + "BA": "Bosnia And Herzegovina", + "BW": "Botswana", + "BV": "Bouvet Island", + "BR": "Brazil", + "IO": "British Indian Ocean Territory", + "BN": "Brunei Darussalam", + "BG": "Bulgaria", + "BF": "Burkina Faso", + "BI": "Burundi", + "KH": "Cambodia", + "CM": "Cameroon", + "CA": "Canada", + "CV": "Cape Verde", + "KY": "Cayman Islands", + "CF": "Central African Republic", + "TD": "Chad", + "CL": "Chile", + "CN": "China", + "CX": "Christmas Island", + "CC": "Cocos (Keeling) Islands", + "CO": "Colombia", + "KM": "Comoros", + "CG": "Congo", + "CD": "Congo, Democratic Republic", + "CK": "Cook Islands", + "CR": "Costa Rica", + "CI": "Cote D'Ivoire", + "HR": "Croatia", + "CU": "Cuba", + "CY": "Cyprus", + "CZ": "Czech Republic", + "DK": "Denmark", + "DJ": "Djibouti", + "DM": "Dominica", + "DO": "Dominican Republic", + "EC": "Ecuador", + "EG": "Egypt", + "SV": "El Salvador", + "GQ": "Equatorial Guinea", + "ER": "Eritrea", + "EE": "Estonia", + "ET": "Ethiopia", + "FK": "Falkland Islands (Malvinas)", + "FO": "Faroe Islands", + "FJ": "Fiji", + "FI": "Finland", + "FR": "France", + "GF": "French Guiana", + "PF": "French Polynesia", + "TF": "French Southern Territories", + "GA": "Gabon", + "GM": "Gambia", + "GE": "Georgia", + "DE": "Germany", + "GH": "Ghana", + "GI": "Gibraltar", + "GR": "Greece", + "GL": "Greenland", + "GD": "Grenada", + "GP": "Guadeloupe", + "GU": "Guam", + "GT": "Guatemala", + "GG": "Guernsey", + "GN": "Guinea", + "GW": "Guinea-Bissau", + "GY": "Guyana", + "HT": "Haiti", + "HM": "Heard Island & Mcdonald Islands", + "VA": "Holy See (Vatican City State)", + "HN": "Honduras", + "HK": "Hong Kong", + "HU": "Hungary", + "IS": "Iceland", + "IN": "India", + "ID": "Indonesia", + "IR": "Iran, Islamic Republic Of", + "IQ": "Iraq", + "IE": "Ireland", + "IM": "Isle Of Man", + "IL": "Israel", + "IT": "Italy", + "JM": "Jamaica", + "JP": "Japan", + "JE": "Jersey", + "JO": "Jordan", + "KZ": "Kazakhstan", + "KE": "Kenya", + "KI": "Kiribati", + "KR": "Korea", + "KW": "Kuwait", + "KG": "Kyrgyzstan", + "LA": "Lao People's Democratic Republic", + "LV": "Latvia", + "LB": "Lebanon", + "LS": "Lesotho", + "LR": "Liberia", + "LY": "Libyan Arab Jamahiriya", + "LI": "Liechtenstein", + "LT": "Lithuania", + "LU": "Luxembourg", + "MO": "Macao", + "MK": "Macedonia", + "MG": "Madagascar", + "MW": "Malawi", + "MY": "Malaysia", + "MV": "Maldives", + "ML": "Mali", + "MT": "Malta", + "MH": "Marshall Islands", + "MQ": "Martinique", + "MR": "Mauritania", + "MU": "Mauritius", + "YT": "Mayotte", + "MX": "Mexico", + "FM": "Micronesia, Federated States Of", + "MD": "Moldova", + "MC": "Monaco", + "MN": "Mongolia", + "ME": "Montenegro", + "MS": "Montserrat", + "MA": "Morocco", + "MZ": "Mozambique", + "MM": "Myanmar", + "NA": "Namibia", + "NR": "Nauru", + "NP": "Nepal", + "NL": "Netherlands", + "AN": "Netherlands Antilles", + "NC": "New Caledonia", + "NZ": "New Zealand", + "NI": "Nicaragua", + "NE": "Niger", + "NG": "Nigeria", + "NU": "Niue", + "NF": "Norfolk Island", + "MP": "Northern Mariana Islands", + "NO": "Norway", + "OM": "Oman", + "PK": "Pakistan", + "PW": "Palau", + "PS": "Palestinian Territory, Occupied", + "PA": "Panama", + "PG": "Papua New Guinea", + "PY": "Paraguay", + "PE": "Peru", + "PH": "Philippines", + "PN": "Pitcairn", + "PL": "Poland", + "PT": "Portugal", + "PR": "Puerto Rico", + "QA": "Qatar", + "RE": "Reunion", + "RO": "Romania", + "RU": "Russian Federation", + "RW": "Rwanda", + "BL": "Saint Barthelemy", + "SH": "Saint Helena", + "KN": "Saint Kitts And Nevis", + "LC": "Saint Lucia", + "MF": "Saint Martin", + "PM": "Saint Pierre And Miquelon", + "VC": "Saint Vincent And Grenadines", + "WS": "Samoa", + "SM": "San Marino", + "ST": "Sao Tome And Principe", + "SA": "Saudi Arabia", + "SN": "Senegal", + "RS": "Serbia", + "SC": "Seychelles", + "SL": "Sierra Leone", + "SG": "Singapore", + "SK": "Slovakia", + "SI": "Slovenia", + "SB": "Solomon Islands", + "SO": "Somalia", + "ZA": "South Africa", + "GS": "South Georgia And Sandwich Isl.", + "ES": "Spain", + "LK": "Sri Lanka", + "SD": "Sudan", + "SR": "Suriname", + "SJ": "Svalbard And Jan Mayen", + "SZ": "Swaziland", + "SE": "Sweden", + "CH": "Switzerland", + "SY": "Syrian Arab Republic", + "TW": "Taiwan", + "TJ": "Tajikistan", + "TZ": "Tanzania", + "TH": "Thailand", + "TL": "Timor-Leste", + "TG": "Togo", + "TK": "Tokelau", + "TO": "Tonga", + "TT": "Trinidad And Tobago", + "TN": "Tunisia", + "TR": "Turkey", + "TM": "Turkmenistan", + "TC": "Turks And Caicos Islands", + "TV": "Tuvalu", + "UG": "Uganda", + "UA": "Ukraine", + "AE": "United Arab Emirates", + "GB": "United Kingdom", + "US": "United States", + "UM": "United States Outlying Islands", + "UY": "Uruguay", + "UZ": "Uzbekistan", + "VU": "Vanuatu", + "VE": "Venezuela", + "VN": "Viet Nam", + "VG": "Virgin Islands, British", + "VI": "Virgin Islands, U.S.", + "WF": "Wallis And Futuna", + "EH": "Western Sahara", + "YE": "Yemen", + "ZM": "Zambia", + "ZW": "Zimbabwe" + }, + "about":{ + "title": "About BeamMP", + "description": "BeamMP brings multiplayer to BeamNG.drive. It’s built by and for the community, focusing on stability, performance, and an authentic driving experience shared with friends.", + "note": { + "title": "A Note from the Creator", + "content": "BeamMP started with a simple idea: I want to play BeamNG.drive with my brothers. What began as an experiment quickly grew into a community-driven project focused on implementing multiplayer, and fun. We care deeply about trying to provide the best experience possible, and making it easy for players to hop in and enjoy driving together. The project is open to contributors of all skill levels. Whether you write code, moderate a server, design scenarios, or help others get set up—your efforts are part of what makes BeamMP thrive. Thank you for being here and helping us build something special." + }, + "provides": { + "title": "What BeamMP Provides", + "points": { + "0": "Multiplayer sessions for BeamNG.drive with server browser and filters", + "1": "Server-side moderation tools and configuration options", + "2": "Mod support with protection for paid content", + "3": "Active community channels (Forum, Discord) for help and collaboration" + } + }, + "project": { + "title": "Project Values", + "points": { + "0": "Community-first: decisions guided by real player/server needs", + "1": "Reliability: prioritizing stability, sync fidelity, and performance where possible", + "2": "Openness: welcoming contributions, feedback, and transparency", + "3": "Safety: promoting fair play and respectful interactions" + } + }, + "get_involved": { + "title": "Get Involved", + "description": "There are many ways to participate—join discussions, report issues, contribute code, or help to support the project financially via", + "patreon": "Patreon", + "forum": "Forums", + "docs": "Docs", + "github": "GitHub", + "discord": "Discord" + }, + "funding": { + "title": "Funding & Sustainability", + "description": "BeamMP relies on community support. Donations help cover infrastructure, bandwidth, tooling, and development time. If you value the project and want to help it grow, please consider supporting us.", + "patreon": "Support us on Patreon", + "learn": "Learn more on GitHub" + }, + "credits": { + "title": "Credits & Acknowledgements", + "description": "BeamMP is maintained by the Mod Team and an incredible group of community contributors. We’d also like to thank server owners, mod creators, testers, and everyone reporting issues—your time and passion keep the project moving forward.", + "desc_2": "Special thanks to the BeamNG.drive developers for creating such an amazing platform that makes multiplayer possible.", + "desc_3": "Also a heartfelt thank you to the following current and former community members for their significant contributions to BeamMP over the years:", + "mentions": { + "0": "Jojos38 (Co-Founder) - for their work early on with designing everything to help make the idea become a reality", + "1": "Jetta (jetta.cat) - for the logo design and creation.", + "2": "Anonymous275 & Lionkor - for their work in rebuilding the project in C++.", + "3": "Tixx - for their considerable contributions across the project codebase.", + "4": "And many more—thank you to everyone who has contributed in any way!" + }, + "thank_you": "Together, we’re building something special. Thank you for being part of the BeamMP community!" + } + } + } +} diff --git a/src/main.js b/src/main.js index 6bd6f35..d6b0ad4 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,26 @@ import { createApp } from 'vue' +//import { createI18n } from 'vue-i18n' +import { setupI18n } from './i18n' import App from './App.vue' -import router from './routes' import './style.css' -createApp(App).use(router).mount('#app') +//const i18n = createI18n({ +const i18n = setupI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + en: await import('./locales/en.json'), + //fr: () => import('./locales/fr.json'), + //es: () => import('./locales/es.json'), + }, +}) + +window.i18n = i18n +window.locale = i18n.global.locale + +import router from './routes' + +createApp(App) + .use(i18n) + .use(router) + .mount('#app') diff --git a/src/routes/index.js b/src/routes/index.js index 0f83d6f..17aed60 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,3 +1,4 @@ +import { loadLocaleMessages, setI18nLanguage, SUPPORT_LOCALES } from '@/i18n' import { createRouter, createWebHistory } from 'vue-router' import NotFound from '@/views/NotFound.vue' @@ -80,7 +81,22 @@ const router = createRouter({ }) // Global navigation guard for meta data -router.beforeEach((to, from, next) => { +router.beforeEach(async (to, from, next) => { + const paramsLocale = to.params.locale || 'en' + + // use locale if paramsLocale is not in SUPPORT_LOCALES + /*if (!SUPPORT_LOCALES.includes(paramsLocale)) { + return next(`/${locale}`) + }*/ + + // load locale messages + if (!i18n.global.availableLocales.includes(paramsLocale)) { + await loadLocaleMessages(i18n, paramsLocale) + } + + // set i18n language + setI18nLanguage(i18n, paramsLocale) + // Set page title document.title = to.meta.title || 'BeamMP' diff --git a/src/views/About.vue b/src/views/About.vue index 75fe81e..a2e2e6e 100644 --- a/src/views/About.vue +++ b/src/views/About.vue @@ -5,11 +5,10 @@

- About BeamMP + {{ $t('message.about.title') }}

- BeamMP brings multiplayer to BeamNG.drive. It’s built by and for the community, focusing on - stability, performance, and an authentic driving experience shared with friends. + {{ $t('message.about.description') }}

@@ -18,19 +17,11 @@ class="rounded-lg border border-neutral-200 dark:border-neutral-800 bg-white/70 dark:bg-neutral-900/60 p-6 mb-10" >

- A Note from the Creator + {{ $t('message.about.note.title') }}

- BeamMP started with a simple idea: I want to play BeamNG.drive with my brothers. What - began as an experiment quickly grew into a community-driven project focused on - implementing multiplayer, and fun. We care deeply about trying to provide the best - experience possible, and making it easy for players to hop in and enjoy driving together. -

-

- The project is open to contributors of all skill levels. Whether you write code, moderate - a server, design scenarios, or help others get set up—your efforts are part of what makes - BeamMP thrive. Thank you for being here and helping us build something special. + {{ $t('message.about.note.content') }}

@@ -39,40 +30,39 @@

- What BeamMP Provides + {{ $t('message.about.provides.title') }}

    -
  • Multiplayer sessions for BeamNG.drive with server browser and filters
  • -
  • Server-side moderation tools and configuration options
  • -
  • Mod support with protection for paid content
  • -
  • Active community channels (Forum, Discord) for help and collaboration
  • +
  • {{ $t('message.about.provides.points.0') }}
  • +
  • {{ $t('message.about.provides.points.1') }}
  • +
  • {{ $t('message.about.provides.points.2') }}
  • +
  • {{ $t('message.about.provides.points.3') }}
-

Project Values

+

+ {{ $t('message.about.project.title') }} +

    -
  • Community-first: decisions guided by real player/server needs
  • -
  • - Reliability: prioritizing stability, sync fidelity, and performance where possible -
  • -
  • Openness: welcoming contributions, feedback, and transparency
  • -
  • Safety: promoting fair play and respectful interactions
  • +
  • {{ $t('message.about.project.points.0') }}
  • +
  • {{ $t('message.about.project.points.1') }}
  • +
  • {{ $t('message.about.project.points.2') }}
  • +
  • {{ $t('message.about.project.points.3') }}
-

Get Involved

+

{{ $t('message.about.get_involved.title') }}

- There are many ways to participate—join discussions, report issues, contribute code, or help - to support the project financially via + {{ $t('message.about.get_involved.description') }} Patreon{{ $t('message.about.get_involved.patreon') }}.

@@ -81,28 +71,28 @@ target="_blank" rel="noopener noreferrer" class="px-4 py-2 rounded-md bg-neutral-100 hover:bg-neutral-200 text-neutral-900 dark:bg-neutral-800 dark:text-white dark:hover:bg-neutral-700 transition-colors" - >Forum{{ $t('message.about.get_involved.forum') }} Docs{{ $t('message.about.get_involved.docs') }} GitHub{{ $t('message.about.get_involved.github') }} Discord{{ $t('message.about.get_involved.discord') }} - Patreon + {{ $t('message.about.get_involved.patreon') }}
@@ -118,12 +108,10 @@

- Funding & Sustainability + {{ $t('message.about.funding.title') }}

- BeamMP relies on community support. Donations help cover infrastructure, bandwidth, tooling, - and development time. If you value the project and want to help it grow, please consider - supporting us. + {{ $t('message.about.funding.description') }}

@@ -148,34 +136,26 @@

- Credits & Acknowledgements + {{ $t('message.about.credits.title') }}

- BeamMP is maintained by the Mod Team and an incredible group of community contributors. We’d - also like to thank server owners, mod creators, testers, and everyone reporting issues—your - time and passion keep the project moving forward. + {{ $t('message.about.credits.description') }}

- Special thanks to the BeamNG.drive developers for creating such an amazing platform that - makes projects like BeamMP possible in the first place. + {{ $t('message.about.credits.desc_2') }}

- Also a heartfelt thank you to the following current and former community members for their - significant contributions to BeamMP over the years: + {{ $t('message.about.credits.desc_3') }}

    -
  • - Jojos38 (Co-Founder) - for their work early on with designing everything to help make the - idea become a reality -
  • -
  • Jetta (jetta.cat) - for the logo design and creation.
  • -
  • Anonymous275 & Lionkor - for their work in rebuilding the project in C++.
  • -
  • Tixx - for their considerable contributions across the project codebase.
  • -
  • And many others!
  • +
  • {{ $t('message.about.credits.mentions.0') }}
  • +
  • {{ $t('message.about.credits.mentions.1') }}
  • +
  • {{ $t('message.about.credits.mentions.2') }}
  • +
  • {{ $t('message.about.credits.mentions.3') }}
  • +
  • {{ $t('message.about.credits.mentions.4') }}

- Together, we’re building something special. Thank you for being part of the BeamMP - community! + {{ $t('message.about.credits.thank_you') }}

diff --git a/src/views/Communities.vue b/src/views/Communities.vue index b43aa84..3943abe 100644 --- a/src/views/Communities.vue +++ b/src/views/Communities.vue @@ -129,11 +129,10 @@ const communities = [

- BeamMP Communities + {{ $t('message.communities.title') }}

- Discover thriving communities built around BeamMP. From competitive racing leagues to casual - free roam sessions, find your perfect group to play with. + {{ $t('message.communities.description') }}

@@ -251,9 +250,9 @@ const communities = [
-

Want to Start Your Own Community?

+

{{ $t('message.communities.starting') }}

- Host your own BeamMP server and build a community around your favorite game modes + {{ $t('message.communities.starting.description') }}

diff --git a/src/views/Home.vue b/src/views/Home.vue index d6452c6..a4368a3 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -13,6 +13,8 @@ import { Shield, Rocket, } from 'lucide-vue-next' +import { useI18n } from 'vue-i18n' +const { t } = useI18n() const onlinePlayers = ref('...') const onlineServers = ref('...') @@ -39,53 +41,49 @@ onMounted(async () => { const features = [ { icon: Server, - title: 'Stable Servers', - description: - 'BeamMP allows for stable servers, with a variety of servers located across the globe.', + title: t('message.home.features.stable_servers.title'), + description: t('message.home.features.stable_servers.description'), }, { icon: Package, - title: 'BeamNG.drive', - description: - "BeamMP uses the same maps, vehicles & mods so you don't need to learn anything new!", + title: t('message.home.features.beamng.title'), + description: t('message.home.features.beamng.description'), }, { icon: Zap, - title: 'Standalone', - description: - "BeamMP doesn't modify your original installation, so you can play either singleplayer or multiplayer.", + title: t('message.home.features.standalone.title'), + description: t('message.home.features.standalone.description'), }, { icon: Globe, - title: 'Sync Quality', - description: - 'BeamMP updates your vehicle position ~100 times per second, allowing for a smooth overall experience.', + title: t('message.home.features.sync.title'), + description: t('message.home.features.sync.description'), }, ] const communities = [ { - name: 'Racing Communities', + name: t('message.home.communities.racing.name'), icon: Rocket, - description: 'Competitive racing leagues and time trials with players worldwide', + description: t('message.home.communities.racing.description'), color: 'from-red-500 to-orange-500', }, { - name: 'Roleplay Servers', + name: t('message.home.communities.roleplay.name'), icon: Gamepad2, - description: 'Immersive roleplay experiences from police chases to delivery services', + description: t('message.home.communities.roleplay.description'), color: 'from-blue-500 to-cyan-500', }, { - name: 'Crash & Derby', + name: t('message.home.communities.crash.name'), icon: Shield, - description: 'Demolition derbies and destruction-focused gameplay modes', + description: t('message.home.communities.crash.description'), color: 'from-purple-500 to-pink-500', }, { - name: 'Free Roam', + name: t('message.home.communities.freeroam.name'), icon: Globe, - description: 'Casual multiplayer sessions exploring maps with friends', + description: t('message.home.communities.freeroam.description'), color: 'from-green-500 to-emerald-500', }, ] @@ -93,60 +91,53 @@ const communities = [ const devFeatures = [ { icon: Code, - title: 'Lua API', - description: 'Powerful server-side Lua scripting for custom game modes and features', - link: 'https://docs.beammp.com/scripting/mod-reference/', + title: t('message.home.devFeatures.lua.title'), + description: t('message.home.devFeatures.lua.description'), + link: 'https://docs.beammp.com/' + (locale == 'en' ? '' : locale + '/') + 'scripting/mod-reference/', }, { icon: BookOpen, - title: 'Documentation', - description: 'Comprehensive guides and API references for server development', - link: 'https://docs.beammp.com', + title: t('message.home.devFeatures.docs.title'), + description: t('message.home.devFeatures.docs.description'), + link: 'https://docs.beammp.com' + (locale == 'en' ? '' : locale + '/'), }, { icon: Wrench, - title: 'Open Source', - description: 'Community-driven development with source available on GitHub', + title: t('message.home.devFeatures.openSource.title'), + description: t('message.home.devFeatures.openSource.description'), link: 'https://github.com/BeamMP', }, ] const stats = [ - { label: 'Active Players', value: onlinePlayers, suffix: '+' }, - { label: 'Global Servers', value: '500', suffix: '+' }, - { label: 'Total Downloads', value: '2M', suffix: '+' }, + { label: t('message.home.metrics.active_players'), value: onlinePlayers, suffix: '+' }, + { label: t('message.home.metrics.public_servers'), value: '500', suffix: '+' }, + { label: t('message.home.metrics.all_servers'), value: '2M', suffix: '+' }, ] - const faqs = [ { - question: 'The server list is not showing up!', - answer: - 'Try restarting BeamMP as this can sometimes happen. If this fails to fix your issue please create a topic on our forum or visit the support channel on our discord.', + question: t('message.home.faq["0"].question'), + answer: t('message.home.faq["0"].answer'), }, { - question: "How do I open a ticket in case something doesn't work or I have questions?", - answer: - 'Please check the #how-to-use channel in Discord and on our forum. Please give an accurate description of what you have done so the support team will help you in a fast and effective way.', + question: t('message.home.faq["1"].question'), + answer: t('message.home.faq["1"].answer'), }, { - question: "Help! I'm getting error codes", - answer: - 'Please head over to our forum and see if anyone has had the issue before. It is likely that someone else has at some point and therefore there will also probably be a solution posted with it too in the replies. Alternatively visit our discord where the larger portion of community is currently based.', + question: t('message.home.faq["2"].question'), + answer: t('message.home.faq["2"].answer'), }, { - question: 'Does this work with pirated versions of BeamNG.drive?', - answer: - "We don't know if it works with pirated versions of BeamNG.drive, but we will not provide any support to non legit copies of the game. Nor will we change to support it.", + question: t('message.home.faq["3"].question'), + answer: t('message.home.faq["3"].answer'), }, { - question: 'How do I host a server?', - answer: - 'The server files required for hosting your own server can be found at the top of this page below the client download. You will also require an authentication key which can be found from keymaster. Further information around the setup can be found on our wiki.', + question: t('message.home.faq["4"].question'), + answer: t('message.home.faq["4"].answer'), }, { - question: 'Can I use mods?', - answer: - 'Mods are supported. These are installed on the server. See our wiki for more information.', + question: t('message.home.faq["5"].question'), + answer: t('message.home.faq["5"].answer'), }, ] @@ -171,12 +162,9 @@ const faqs = [
-

- Multiplayer for BeamNG.drive -

+

- Experience the ultimate soft-body physics with friends. Race, roleplay, or just cruise - together. + {{ $t('message.home.hero.subtitle') }}

@@ -187,14 +175,14 @@ const faqs = [ class="group flex items-center gap-3 bg-linear-to-r from-beammp-orange to-red-600 hover:from-red-600 hover:to-beammp-orange px-8 py-4 rounded-lg font-semibold text-lg transition-all transform hover:scale-105 shadow-lg hover:shadow-beammp-orange/50" > - Download Now + {{ $t('message.home.hero.download_now') }} - Browse Servers + {{ $t('message.home.hero.browse_servers') }}
@@ -244,9 +232,9 @@ const faqs = [
-

Join a Thriving Community

+

{{ $t('message.home.communities.join') }}

- Discover diverse gameplay experiences across hundreds of unique servers + {{ $t('message.home.communities.description') }}

@@ -276,10 +264,9 @@ const faqs = [
-

Find Your Perfect Server

+

{{ $t('message.home.find.title') }}

- Browse hundreds of active servers with different game modes, mods, and communities. From - competitive racing to casual free roam, there's something for everyone. + {{ $t('message.home.find.description') }}

  • @@ -289,9 +276,9 @@ const faqs = [
    -
    Custom Game Modes
    +
    {{ $t('message.home.find.points.custom') }}
    - Unique experiences created by the community + {{ $t('message.home.find.points.custom_desc') }}
  • @@ -302,9 +289,9 @@ const faqs = [
    -
    Active Moderation
    +
    {{ $t('message.home.find.points.moderation') }}
    - Safe and friendly gaming environment + {{ $t('message.home.find.points.moderation_desc') }}
    @@ -315,9 +302,9 @@ const faqs = [
    -
    Global Network
    +
    {{ $t('message.home.find.points.global') }}
    - Servers in every region for low latency + {{ $t('message.home.find.points.global_desc') }}
    @@ -326,7 +313,7 @@ const faqs = [ href="/servers" class="inline-flex items-center gap-2 bg-beammp-blue hover:bg-beammp-blue/90 text-white px-6 py-3 rounded-lg font-semibold transition-colors" > - Browse All Servers + {{ $t('message.home.find.browse_all_servers') }}
@@ -342,9 +329,9 @@ const faqs = [
-

Built for Developers

+

{{ $t('message.home.devFeatures.title') }}

- Create custom game modes, host your own server, and contribute to the project + {{ $t('message.home.devFeatures.description') }}

@@ -366,7 +353,7 @@ const faqs = [
- Learn More + {{ $t('message.home.devFeatures.learn_more') }}
-

Ready to Host Your Own Server?

+

{{ $t('message.home.devFeatures.host.title') }}

- Download the server files and create your own unique BeamMP experience + {{ $t('message.home.devFeatures.host.description') }}

@@ -426,7 +413,7 @@ const faqs = [
-

FAQ

+

{{ $t('message.home.faq.title') }}

404 -

Page Not Found

+

{{ $t("message.404.title") }}

- The page you requested doesn’t exist. It may have been moved or removed. + {{ $t("message.404.description") }}

- Return Home + {{ $t("message.404.return_home") }} - Browse Servers + {{ $t("message.home.hero.browse_servers") }}
diff --git a/src/views/Servers.vue b/src/views/Servers.vue index 7640051..df2bef8 100644 --- a/src/views/Servers.vue +++ b/src/views/Servers.vue @@ -1,8 +1,8 @@