Building a multilingual website using AngularJS UI-Router

I am currently working on developing a multilingual website using AngularJS. While providing translations in templates seems straightforward, I am facing challenges when it comes to implementing proper multilingual routes using UI-Router. Unfortunately, I have not been able to find suitable examples to guide me through this process.

The goal is to easily scale the website when adding new languages. For example, the structure of routes for two languages would look like:

/en
/en/products
/en/products/green-category
/en/products/green-category/green-product-1

/cs
/cs/produkty
/cs/produkty/zelena-kategorie
/cs/produkty/zelena-kategorie/zeleny-produkt-1

While product categories are hardcoded, products are dynamically loaded from the database.

My attempted solution looks something like this (excluding product categories as they follow a similar structure to 'products', just one level deeper):

$stateProvider.state('product', {
    url: '/{lang:' + Translate.getLangs() + '}/{products:' + Translate.getRouteVariants('products') + '}/{productSlug}',
    templateUrl: 'app/product.html',
    resolve: {
        product : function($stateParams){
            return Data.products.get( Data.products.deslug($stateParams.productSlug, $stateParams.lang), $stateParams.lang );
        }
    }
});

And in controller / template:

$scope.productLink = function(id) {
    return {
        lang:$rootScope.lang,
        products:Translate.getRoute('products', $rootScope.lang),
        productSlug:Data.products.slug(1, $rootScope.lang)
    };
}

<a ui-sref="product(productLink(1))">Green product 1</a>

Where

Translate and Data are providers
Translate.getLangs() -> 'en|cs'
Translate.getRoute('products', lang) -> 'products' or 'produkty' depending on language
Translate.getRouteVariants('products') -> 'products|produkty'

Data.products.slug(productId, lang) -> returns productSlug from model
Data.products.deslug(productSlug, lang) -> returns productId from model
Data.products.get(productId, lang) -> loads data

This current method of handling the language could be improved (likely within the Translate provider).

The issue of preventing cross-language URLs such as '/en/produkty' is a major concern. /edit: I might consider using $stateChangeStart to validate whether all parameters match one language and if not, redirect to the top-level state.

This whole solution may not be the most elegant (given my beginner status with Angular), so any insights or guidance on this matter would be greatly appreciated.

Thank you.

Answer №1

Let me share a key point with you regarding the display of multi-lingual content, especially if your presentation remains consistent regardless of language or locale. The crucial aspect to remember is...

Avoid duplicating your view/presentation code.

Repeating your code can lead to duplication and potential issues down the line.

If you do wish to keep separate templates, there might be an issue with the following line:

url: '/{lang:' + Translate.getLangs() + '}/{products:' + Translate.getRouteVariants('products') + '}/{productSlug}',

When using curly braces, the text after : is considered a regular expression. Therefore, you cannot simply return something like 'en|ch' for getLangs(), it should be formatted as

'[a-z][a-z]{en|ch}'

(Although untested, this should work as intended.)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

`Firefoxx border table glitch`

When attempting to open/close tables in Firefox using this link, unnecessary borders appear. One way to fix this issue is by implementing the following JS solution: setTimeout(function () { $table.css({'table-layout': 'auto'}) ...

Is there a way to make elasticX() and elasticY() only affect the upper bound in dc.js?

One question I have regarding my bubbleChart in dc.js is related to the x-axis. I want the count on the x-axis to always start at 0, but have an upper bound that adjusts based on the range I am looking at. Currently, when I use .elasticX(true), both the up ...

Strange flickering/visualization issue experienced with transparent MeshPhongMaterial in Three.JS

In my scene, I have a Mesh called cylinder: const cylinder = new Mesh( new CylinderGeometry(2, 2, 1, 32), new MeshPhongMaterial({ color: color, shininess: 32, opacity: 0, transparent: true, specular: 0xffff82, }), ); I made the ...

What is the best way to extract the body content from a Markdown file that includes Frontmatter

How can I retrieve the content of the body from my markdown file using front matter? Currently, it is displaying as undefined. What steps should I take to fix this issue? {latest.map(({ url, frontmatter }) => ( <PostCard url={url} content={frontmat ...

`res.render when all data queries are completed``

When I make an app.get request in my server.js file, I retrieve a dataset from MongoDB and then render my page while passing the data to it. Here is an example: //page load app.get('/', (req, res) => { //find all data in test table ...

Validation of default values in contact forms

Obtained a free contact form online and hoping it works flawlessly, but struggling with validation for fields like "Full Name" in JS and PHP. Here is the HTML code: <input type="text" name="contactname" id="contactname" class="required" role="inpu ...

Creating specialized paths for API - URL handlers to manage nested resources

When working with two resources, employees and employee groups, I aim to create a structured URL format as follows: GET /employees List employees. GET /employees/123 Get employee 123. GET /employees/groups List employee groups. GET /employees/groups/123 ...

I've come across this ajax url that seems promising, but I keep getting a GET 404 (Not Found)

I am attempting to validate using ajax and php. This is the code I have for my ajax: function PrintRecibopapel() { recibo = document.getElementById("txtCod").value; if(recibo == "") { alert("You must save the receipt before pr ...

Add a CSS and jQuery hover effect to display text over an image, requiring users to click twice on their mobile device

I have a bunch of panels for different categories that change the background image when hovered over, display some introductory text, and lead to a URL when clicked. However, on mobile devices, you need to tap the panel twice to activate the URL. What I&a ...

The attempt to add a note with a POST request to the /api/notes/addnote endpoint resulted in a

I'm facing an issue while trying to send a POST request to the /api/notes/addnote endpoint. The server is returning a 404 Not Found error. I have checked the backend code and made sure that the endpoint is correctly defined. Here are the specifics of ...

Step-by-step guide on inserting a div element or hotspot within a 360 panorama image using three.js

As I work on creating a virtual tour using 360 images, I am looking to include hotspots or div elements within the image that can be clicked. How can I store data in my database from the event values such as angle value, event.clientX, and event.clientY wh ...

Nested ng-repeats within ng-repeats

I have a question regarding the correct way to utilize an inner ng-repeat inside of an outer ng-repeat: Essentially, I am looking to implement something along these lines: <tr ng-repeat="milestone in order.milestones"> <td>{{mi ...

Problem with custom anchor component in React that needs to perform an action before being clicked

React Component (Custom Anchor) import React from 'react'; class Anchor extends React.Component { onClick = (event) => { // ----------------------------- // send Google Analytics request ...

Issue with jQuery .hover() not functioning as expected

The issue I'm encountering is just as described in the title. The code functions correctly on all divs except for one! $(".complete-wrapper-1").hide(); var panelHH = $(".file-select-wrapper").innerHeight; $(".files-button").hover(function(){ $(" ...

Bypassing the "Your connection is not private" error in NodeJS + Express with fetch() using Javascript

Presently, I have a setup with a NodeJS + ExpressJS client-side server that communicates with the back-end server via API calls. However, every time I make a call, I need to manually navigate to the URL of the API back-end server and click on Advanced -> ...

Is there a way to achieve a similar effect to "object-fit: cover" for CylinderGeometry in three.js while utilizing THREE.VideoTexture()?

I'm really interested in creating something similar to this: https://i.sstatic.net/mWuDM.png Imagine the checkered background as a texture, and I want the jar to be a cylinder with that texture applied to it. My knowledge of three.js is limited, so ...

Is it possible to use multiple AJAX requests to automatically fill out form fields?

In my Backbone.js web application, there is a form with multiple dropdowns that need to be populated with data fetched from an API. Since all the application logic resides on the client side due to using Backbone.js, I want to avoid populating these dropd ...

Transferring the state from a parent component to a child function

I'm having trouble passing a state from a component to a function. I was able to pass the state from Home to ListHome, but I'm struggling to continue passing it to a function within ListHome (Slider) because it's a function. Even after revi ...

JavaScript Numbers Having Strange Behavior

Insight The highest integer that can safely be stored in JavaScript is 9007199254740991 link Dilemma 1000000000000 === 999999999999.999999 // Returns true 1000000000000 === 999999999999.99999 // Returns true 1000000000000 === 999999999999.9999 // Re ...

Even when the outcome is not what was anticipated, mocha chai still manages to ace the examination

When testing my REST API response with mocha, chai, and express, I set the expected status to 201 but unexpectedly got a passing test result it('janus post', () => { request('https://***') .post('/***') .attach(&a ...