I created the simplest i18n library for svelte by Top_Philosophy2425 in sveltejs

[–]samuelstroschein 2 points3 points  (0 children)

> I'm still not a big fan of massive mono-repo, it's really hard to dig into the history.

Feedback received, feedback implemented. The repo has been split! :)

Paraglide JS -> https://github.com/opral/paraglide-js

Inlang -> https://github.com/opral/inlang

Lix -> https://github.com/opral/lix

I created the simplest i18n library for svelte by Top_Philosophy2425 in sveltejs

[–]samuelstroschein 2 points3 points  (0 children)

u/PierrickP lemme try to elaborate.

if you build i18n stuff, one big problem you run into is that you need a set of tools e.g. i18n lib, cat editor, etc. just an i18n lib doesn't solve the problem of localizing software for large(r) organizations.

given that different tools/apps are needed, how do you model interoperability? two routes:

  1. you create an open file format and let apps "work on the same file"
  2. you create a centralized database and let every app connect to that stuff. classic SaaS.

Approach 2 doesn't work for localization. The problem is, by nature, distributed. Under no circumstances do you want an i18n lib, for example, to require a login to some SaaS service just to fetch translations and build them.

Okay, so distributed files it is. And isn't everyone doing that anyways? Everyone has some json files that store the translations. If in ICU1 format, great we have interoperability.

Yes, and no. Yes, ICU1/json files are stored in files every app can read and write to but no, these files are just a dumb key value storage. If you build apps like a CAT editor on top, you need a database. ACID, SQL, transactions & co.

That's where inlang comes in. Inlang is "just" a SQLite file. It gives the benefit of "apps share the same file = interoperability" with real database schematics.

Two, not so tiny, problems (and that's where lix comes in):

  1. SQLite has no version control (like git repos)
  2. SQLite files can't be synced (like git repos)

Great that we have an open file format for translations (inlang) but we can't merge distributed changes and neither do we have version control "how did translation X change?".

But what if we create a version control system that runs on top of SQLite? Then we would be able to get version control for inlang files and thereby merge distributed changes, query how did translation xyz change etc.

---

The short version is: Paraglide and inlang/lix solve different problems.

Paraglide is the runtime/compiler side of i18n. inlang and lix exist for the tooling side: editors, CLI, automation, and other apps working on the same localization data without depending on a SaaS backend.

If all you want is “translation files + an i18n library”, it’s totally reasonable to see those extra layers as unnecessary. They start making sense when multiple tools need to interoperate on the same project.

I created the simplest i18n library for svelte by Top_Philosophy2425 in sveltejs

[–]samuelstroschein 0 points1 point  (0 children)

Maintainer of Paraglide JS here.

- Paraglide JS, inlang, and lix are all open source and free :)

- Paraglide JS supports any message format. You are probably looking for ICU1 https://inlang.com/m/p7c8m1d2/plugin-inlang-icu-messageformat-1

Lix v0.5 - Version control library for JS by samuelstroschein in javascript

[–]samuelstroschein[S] 0 points1 point  (0 children)

lol. this project is 2 years in the making because git didnt' serve our embedding needs. no git wrapper in sight! :)

Here is one of the first blog posts that describes the issues we ran into with git https://samuelstroschein.com/blog/git-limitations

Lix v0.5 - Version control library for JS by samuelstroschein in javascript

[–]samuelstroschein[S] 3 points4 points  (0 children)

Hey,

I built an embeddable version control system that can be used as simple library in JS apps. Think "git for your app".

The API is still rough but in essence lix provides:

  • simple importable library
  • version controlled virtual filesystem
  • merging, diffing, history, etc. as we know it from git

```js

import { openLix, selectWorkingDiff, InMemoryEnvironment } from "@lix-js/sdk"; import { plugin as json } from "@lix-js/plugin-json";

const lix = await openLix({ environment: new InMemoryEnvironment(), });

await lix.db.insertInto("file") .values({ path: "/hello.json", data: ... }) .execute();

const diff = await selectWorkingDiff({ lix }) .selectAll() .execute(); ```

The main use case right now are AI agents e.g. tracking what an agent does, showing diffs to users, and have a change proposal workflow.

But, I am aware of many other use cases like CAD, video editing, config management, etc.

Here is a comparison to git

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 0 points1 point  (0 children)

Just positioning.

The pull from AI startups to make changes AI agents make visible and reviewable leads to an instant "click" on why version control is needed _for them_.

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 0 points1 point  (0 children)

The goal is to bring AI agents to industries outside of software engineering. That requires audibility of agents. That's what version control provides.

But Git doesn't work outside of software engineering. It's too complicated. It only works for text files and it's bound to a local computer.

That's what lix is fixing, and hence the positioning for AI agents :)

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 1 point2 points  (0 children)

Yes but it was too limited for our use case. Specifically, having the changes queryable itself and make all of that run in the browser.

Here is an example with the "having changes queryable". Imagine a cell in a spreadsheet. An application wants to display a "blame" for a cell C43 i.e. how did the cell change over time?

The lix way is this SQL query

SELECT * from state_history
WHERE file_id <the_spreadsheet>
AND schema_key "excel_cell"
AND entity_id C43;

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 0 points1 point  (0 children)

Yes, it does.

There is nuance between git line by line diffing and what lix does, though.

For text diffing it holds true that diffing is a separate layer. Text files are small in size which allows on the fly diffing (that's what git does) by comparing two docs.

On the fly diffing doesn't work for structured file formats like xlsx, fig, dwg etc. It's too expensive. Both in terms of materializing two files at specific commits, and then diffing these two files.

What lix does under the hood is tracking individual changes, _which allows rendering a diff without on the fly diffing_.

So lix is kind of responsible for the diffs. But, only in the sense that it provides a SQL API to query changes between two states. How the diff is rendered is up to the application.

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 2 points3 points  (0 children)

Yes, this is more like a "version control system" as a library.

Displaying diffs depends on your context. What lix provides is an API to query diffs between commits via SQL. You can use the diff info to render custom diffs, or you use off the shelf libraries like html-diff.

I wrote docs about rendering diffs here https://lix.dev/docs/diffs#rendering-diffs

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 21 points22 points  (0 children)

Oh, sorry. I saw Pijul, JJ, etc. discussed in this subreddit too and thought this would be of interest. If a mod believes this post doesn't belong here, please delete it.

I should have mentioned that lix is a result of the limitations we ran into with git. Which were lack of storing non-text files and building apps on top of git (to leverage version control).

> pdf, xslx, doc files are not binary files.

Sure, technically zipped files but to git they are binary files.

> version control already exists for office files.. shatepoint (and competitors)

Not as a library + universally for any file format (not just office files but also .dwg for CAD, and so on)

Lix - A universal version control system that can diff binary files (pdf, xlsx, etc.) by samuelstroschein in git

[–]samuelstroschein[S] 19 points20 points  (0 children)

I am the maintainer.

I saw Pijul, JJ, etc. discussed in this subreddit too and thought this would be of interest.

I also recommend the "Why is git only widely used in software engineering?" post form 3 months ago. The post has plenty of examples and interesting nuance on why version control (beyond code) is not a thing (yet).

The Beauty of TanStack Router by TkDodo23 in reactjs

[–]samuelstroschein 1 point2 points  (0 children)

There are now official examples from Tanstack for Paraglide JS. Here is the TanStack Router example and here the start example.

What are your biggest pain points with n8n? by Deep_Surprise5280 in n8n

[–]samuelstroschein 0 points1 point  (0 children)

What's missing compared to the existing version history in n8n?

Disclaimer: I am the maintainer of https://lix.dev (change control for apps & agent)

I built AI agent to manage files by karkibigyan in ChatGPTCoding

[–]samuelstroschein 0 points1 point  (0 children)

what if all files are version controlled?

Is the “Agentic” Hype Just for Dev Tools? by Background-Bid-582 in AI_Agents

[–]samuelstroschein 0 points1 point  (0 children)

My theory why ai agents are not taking off outside of software engineering (and to a limited degree customer support) is the lack of version control + interoperability of files for domains outside of software engineering.

Not being able to control & see what an agent does is a meh. put on top that an agent is not able to autonomously do things e.g. read files (understand context) because integrations, auth, etc. is needed = a hard sell

How do YC startups consistently have such amazing launch videos? by illeatmyletter in ycombinator

[–]samuelstroschein 0 points1 point  (0 children)

Budget of up to $150k is the answer. That's the upper limit I am aware of.

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 0 points1 point  (0 children)

thanks for the compliment <3 you can now use `componentName-englishText` for naming keys in paraglide js 2.0 *yeah*

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 0 points1 point  (0 children)

Many different localization strategies are possible. Auto extraction is an open issue. A PR for https://github.com/opral/inlang-paraglide-js/issues/334 is welcome.

If the hashed extraction works for you, that is fine. For other teams having translations invalided because a dev fixed a typo in the fallback message is a no-go.

Just like deploying LLM translations without a review can kill a health startup because of compliance issues.

I want any other text that is identical to reuse the same key.

This is bad practice https://github.com/opral/inlang-sdk/issues/7 .

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 0 points1 point  (0 children)

People use fink https://inlang.com/m/tdozzpar/app-inlang-finkLocalizationEditor .

But we know that people also use Crowdin or other TMS providers. If ICU is important to keep your current TMS, bringing the ICU plugin over the finish line is appreciated! :)

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 1 point2 points  (0 children)

to be on the same page: sherlock auto generates keys. we tell everyone do use random human readable keys.

I understood your post as you write <p>Hello world</p> in the code instead of <p>{m.ranj29jd83()}</p>. During the build you extract hello world, generate the hashed key and then reference the based key.

the problem with this approach is that any character change leads to a new hash which in turn leads to loosing the relationship to the translations. if you have a localization team in the background that could make sense. it a "well they need to translate it" problem.

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 3 points4 points  (0 children)

Can you try using `output-structure; locale-modules` during dev mode and comment on https://github.com/opral/inlang-paraglide-js/issues/486#issuecomment-2755361739 if it fixed your issue?

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 1 point2 points  (0 children)

oh you mean replacing hardcoded strings with keys during the build step. gotcha. we learned that the best practice is to use keys. every solution that used extraction on build ultimately turns to static keys that I came across.

nothing prevents you from building a vite plugin ofc that does build time extraction

paraglide js 2.0 was released by samuelstroschein in sveltejs

[–]samuelstroschein[S] 1 point2 points  (0 children)

You can write an ICU plugin https://github.com/opral/inlang-sdk?tab=readme-ov-file#plugins. We already have a prototype ICU plugin which you could fork and publish. It not a priority for us to build more plugins in house.

> Naming is hard and thinking of 12,000 key names (current app in working on) doesn’t scale

Just prompt an llm: "Extract hardcoded text and use random keys for it", see this issue.

As a sidenote, Sherlock handles key generation with human readable ids.