Skip to content

feat(compiler): custom resolvers#2024

Open
AleksandrSl wants to merge 5 commits intomainfrom
aleksandrsl/custom-resolvers
Open

feat(compiler): custom resolvers#2024
AleksandrSl wants to merge 5 commits intomainfrom
aleksandrsl/custom-resolvers

Conversation

@AleksandrSl
Copy link
Collaborator

@AleksandrSl AleksandrSl commented Mar 1, 2026

Summary

It's an example of having custom resolvers and what we have to do to support them. Ofc we have to make path based i18n support internally along with the cookies, without custom resolvers.

There are both changes on the user side (demo) and our side (in the compiler, because I removed the custom resolver part for simplicity until we have requests, but PR also demonstrates how we can support path based i18n, probably it can also be done a bit cleaner, and we can provide middleware configuration as exported function, so users don't have to do it, similar how next-intl does this. suprisingly they have a ton of code around these)

Changes

  • [Key change 1]
  • [Key change 2]

Testing

Business logic tests added:

  • [Describe test 1 - what behavior it validates]
  • [Describe test 2 - what edge case it covers]
  • All tests pass locally

Visuals

Required for UI/UX changes:

  • Before/after screenshots attached
  • Video demo for interactions (< 30s)

Checklist

  • Changeset added (if version bump needed)
  • Tests cover business logic (not just happy path)
  • No breaking changes (or documented below)

Closes #[issue-number]

There were a bunch of leftover from experiments. e.g. _lingoConfig was a hack, a field with a config copy added to the config object which can be read by the translation-server cli to parse the arguments. But bundlers were always complaining about it, plus in next with our async setup it would not work. So there is no way to parse the config now. We could add some though if needed, but honestly parsing the file and finding our config section.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 1, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b190c568-faa8-425c-a940-820879e2bb7a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch aleksandrsl/custom-resolvers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@AleksandrSl AleksandrSl changed the title Aleksandrsl/custom resolvers feat(compiler): custom resolvers Mar 1, 2026
@AleksandrSl AleksandrSl changed the base branch from main to aleksandrsl/docs-update March 1, 2026 22:30
@@ -1 +1,2 @@
export type { PartialLingoConfig } from "./types";
export type { LocaleCode } from "lingo.dev/spec";
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Makes sense to reexport I think, because it's used in many places, and compiler could be the single dependency.

Comment on lines +74 to +77

export function getLocalePathname(locale) {
return null; // Not used for cookie-based routing
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
export function getLocalePathname(locale) {
return null; // Not used for cookie-based routing
}

if (router) {
router.refresh();
if (newUrl) {
router.push(newUrl);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I missed that for the path based i18n we will have to do navigation. I don't think we need to add a separate method for that, just returning newUrl form persistLocale if redirect is needed sounds reasonable to me.

Next needs a push, because we have to trigger a middleware so that server components get a correct locale

} {
const baseDir = path.join(projectRoot, sourceRoot, lingoDir);

const serverPath = resolveResolverPath("locale-resolver-server", baseDir);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The whole file is a way to check that the file are present where we expect them to be. In this PR I expect them to be in the lingo directory, but we are free to come up with any pattern we want.

Also a nice error if one of the files is missing when custom locale resolver is chosen in settings would be good

process.cwd(),
);

customResolverAliases = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For vite and unplugin there should already be a similar thing.

See

function tryLocalOrReturnVirtual(
  config: LingoConfig,
  fileName: string,
  virtualName: string,
) {
  const customPath = path.join(config.sourceRoot, config.lingoDir, fileName);
  if (fs.existsSync(customPath)) {
    return customPath;
  }
  return virtualName;
}

I don't remember if I checked it working

@@ -0,0 +1,4 @@
import type { LocaleCode } from "@lingo.dev/compiler"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just a way to avoid repeating these

@@ -0,0 +1,107 @@
import { NextRequest, NextResponse } from "next/server";
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's 2026 why the hell Next asks users to configure all this hell when they want path based i18n

@AndreyHirsa AndreyHirsa marked this pull request as ready for review March 4, 2026 08:30
Base automatically changed from aleksandrsl/docs-update to main March 4, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant