Skip to content

feat(@angular/build): add support for customizing URL segments with i18n #29011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 7, 2024

Conversation

alan-agius4
Copy link
Collaborator

@alan-agius4 alan-agius4 commented Dec 2, 2024

Previously, the baseHref option under each locale allowed for generating a unique base href for specific locales. However, users were still required to handle file organization manually, and baseHref appeared to be primarily designed for this purpose.

This commit introduces a new subPath option, which simplifies the i18n process, particularly in static site generation (SSG) and server-side rendering (SSR). When the subPath option is used, the baseHref is ignored. Instead, the subPath serves as both the base href and the name of the directory containing the localized version of the app.

Below is an example configuration showcasing the use of subPath:

"i18n": {
  "sourceLocale": {
    "code": "en-US",
    "subPath": ""
  },
  "locales": {
    "fr-BE": {
      "subPath": "fr",
      "translation": "src/i18n/messages.fr-BE.xlf"
    },
    "de-BE": {
      "subPath": "de",
      "translation": "src/i18n/messages.de-BE.xlf"
    }
  }
}

The following tree structure demonstrates how the subPath organizes localized build output:

dist/
├── app/
│   └── browser/  # Default locale, accessible at `/`
│       ├── fr/  # Locale for `fr-BE`, accessible at `/fr`
│       └── de/  # Locale for `de-BE`, accessible at `/de`

DEPRECATED: The baseHref option under i18n.locales and i18n.sourceLocale in angular.json is deprecated in favor of subPath.

The subPath defines the URL segment for the locale, serving as both the HTML base HREF and the directory name for output. By default, if not specified, subPath will use the locale code.

Closes #16997 and closes #28967

@alan-agius4 alan-agius4 added the target: minor This PR is targeted for the next minor release label Dec 2, 2024
@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: @angular/build labels Dec 2, 2024
@alan-agius4 alan-agius4 force-pushed the ssr-i18n-output-path branch 8 times, most recently from 826631e to 35403a3 Compare December 3, 2024 12:26
@alan-agius4 alan-agius4 closed this Dec 3, 2024
@alan-agius4 alan-agius4 reopened this Dec 3, 2024
@alan-agius4 alan-agius4 force-pushed the ssr-i18n-output-path branch 2 times, most recently from b2e4c60 to 28771a3 Compare December 3, 2024 13:23
@alan-agius4 alan-agius4 added the action: review The PR is still awaiting reviews from at least one requested reviewer label Dec 3, 2024
@alan-agius4 alan-agius4 requested a review from clydin December 3, 2024 13:24
@alan-agius4 alan-agius4 marked this pull request as ready for review December 3, 2024 13:24
@alan-agius4 alan-agius4 force-pushed the ssr-i18n-output-path branch 3 times, most recently from 01430e3 to f758f02 Compare December 4, 2024 13:00
@alan-agius4 alan-agius4 requested a review from dgp1130 December 5, 2024 18:27
Copy link
Collaborator

@dgp1130 dgp1130 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Mostly just some small suggestions to make sure the error cases are clear and understandable to users.

My one thought is whether there is a more clear name than urlSegment we could use? In my mind that really doesn't describe what this will do and without any further context I'd have no idea what to use it for.

"segment" to me also implies it is exactly one segment between slashes, but I'm not sure that's a hard constraint? Users can write urlSegment: 'foo/bar' right? That would look like two segments to me.

Not really sure of an alternative, but we could consider something like localeBase, localeRoot, root (maybe we can rely on the context that this option is only available with a locale), directory, outputDir, subpath, localeBaseHref / baseHref (it does say this serves as "baseHref" in the JSON doc), ...

I'll defer to you on the exact naming, I just want to make sure we're considering alternatives and thinking critically about what this concept represents to users.

@alan-agius4
Copy link
Collaborator Author

I went with subPath for naming.

@alan-agius4 alan-agius4 force-pushed the ssr-i18n-output-path branch 2 times, most recently from 824d4e5 to 55458b3 Compare December 6, 2024 09:55
@angular-robot angular-robot bot added the detected: deprecation PR contains a commit with a deprecation label Dec 6, 2024
@alan-agius4 alan-agius4 force-pushed the ssr-i18n-output-path branch 3 times, most recently from f936df1 to 1fc2f7c Compare December 6, 2024 10:15
Copy link
Member

@clydin clydin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option validation comment, otherwise LGTM.

@alan-agius4 alan-agius4 removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Dec 7, 2024
Previously, the `baseHref` option under each locale allowed for generating a unique base href for specific locales. However, users were still required to handle file organization manually, and `baseHref` appeared to be primarily designed for this purpose.

This commit introduces a new `subPath` option, which simplifies the i18n process, particularly in static site generation (SSG) and server-side rendering (SSR). When the `subPath` option is used, the `baseHref` is ignored. Instead, the `subPath` serves as both the base href and the name of the directory containing the localized version of the app.

Below is an example configuration showcasing the use of `subPath`:

```json
"i18n": {
  "sourceLocale": {
    "code": "en-US",
    "subPath": ""
  },
  "locales": {
    "fr-BE": {
      "subPath": "fr",
      "translation": "src/i18n/messages.fr-BE.xlf"
    },
    "de-BE": {
      "subPath": "de",
      "translation": "src/i18n/messages.de-BE.xlf"
    }
  }
}
```

The following tree structure demonstrates how the `subPath` organizes localized build output:
```
dist/
├── app/
│   └── browser/  # Default locale, accessible at `/`
│       ├── fr/  # Locale for `fr-BE`, accessible at `/fr`
│       └── de/  # Locale for `de-BE`, accessible at `/de`
```

DEPRECATED: The `baseHref` option under `i18n.locales` and `i18n.sourceLocale` in `angular.json` is deprecated in favor of `subPath`.

The `subPath` defines the URL segment for the locale, serving as both the HTML base HREF and the directory name for output. By default, if not specified, `subPath` will use the locale code.

Closes angular#16997 and closes angular#28967
@alan-agius4 alan-agius4 added the action: merge The PR is ready for merge by the caretaker label Dec 7, 2024
@alan-agius4 alan-agius4 merged commit 0a570c0 into angular:main Dec 7, 2024
31 checks passed
@alan-agius4 alan-agius4 deleted the ssr-i18n-output-path branch December 7, 2024 18:00
@hheexx
Copy link

hheexx commented Dec 12, 2024

Is this going to Angular 20 or 19.1?

@alan-agius4
Copy link
Collaborator Author

19.1, which is currently in prerelease.

@hheexx
Copy link

hheexx commented Jan 10, 2025

Hi @alan-agius4 ,

looks like this feature was not present in builds before RC.
Now it's inside so I took a look.

I added to angular.json like this:
image

Slashes made a problem and generated manifest was:
export default {
basePath: '/',
supportedLocales: {
"en": "en",
"sr": "",
"ru": "/ru/"
},
entryPoints: {
'en': () => import('./en/main.server.mjs'),
'': () => import('./main.server.mjs'),
'/ru/': () => import('.//ru//main.server.mjs')
},
};

Russian was not working.
After removing the slashes everything is OK but maybe you want to check why is there different handling between en and ru.

@alan-agius4
Copy link
Collaborator Author

alan-agius4 commented Jan 10, 2025

@hheexx, it looks like the validation function was not being called correctly. #29328

i18n.subPath is not a valid options, the subpath for the sourceLocale needs to be specified in i18n.sourceLocale.subPath. In this case, it worked as it fallbacked to the default value which is en for en. When the subPath is the same as the local code, it does not need to be specified.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Feb 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: @angular/build detected: deprecation PR contains a commit with a deprecation detected: feature PR contains a feature commit target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Set locale baseHref to '/' is not working with AngularNodeAppEngine Allow custom "outputPath" directory for each locale
4 participants