mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-11-03 18:00:11 +00:00 
			
		
		
		
	Add a guide to help with translating
This commit is contained in:
		@@ -4,7 +4,9 @@ weight = 0
 | 
			
		||||
+++
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
You must install [sbt](https://scala-sbt.org) and [Elm](https://elm-lang.org).
 | 
			
		||||
You must install [sbt](https://scala-sbt.org),
 | 
			
		||||
[nodejs](https://www.npmjs.com/get-npm) (for the `npm` command) and
 | 
			
		||||
[Elm](https://elm-lang.org).
 | 
			
		||||
 | 
			
		||||
Clone the sources and run:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										402
									
								
								website/site/content/docs/dev/translation.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										402
									
								
								website/site/content/docs/dev/translation.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,402 @@
 | 
			
		||||
+++
 | 
			
		||||
title = "Translating Web-UI"
 | 
			
		||||
weight = 10
 | 
			
		||||
+++
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Help with translating the web-ui is greatly appreciated. I can only
 | 
			
		||||
provide translations for English and German, and these may be wrong -
 | 
			
		||||
so pointing out mistakes is also appreciated :).
 | 
			
		||||
 | 
			
		||||
Here is a detailed walkthrough for adding a new language. It requires
 | 
			
		||||
to code in [Elm](https://elm-lang.org). But even if you're not a
 | 
			
		||||
programmer, you will be comfortable as it's not difficult for this
 | 
			
		||||
task. Elm is also a nice and friendly language, provding helpful error
 | 
			
		||||
messages.
 | 
			
		||||
 | 
			
		||||
This guide assumes no knowledge about Elm at all.
 | 
			
		||||
 | 
			
		||||
# TL;DR
 | 
			
		||||
 | 
			
		||||
If you are already familiar with Elm, here is the TL;DR:
 | 
			
		||||
 | 
			
		||||
1. Goto `Messages.UiLanguage` in `modules/webapp/src/main/elm` and add
 | 
			
		||||
   another language to the union type and also to the `all` list.
 | 
			
		||||
2. Fix all compile errors by providing a different `Texts` value for
 | 
			
		||||
   the new language.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Prepare
 | 
			
		||||
 | 
			
		||||
You need to install [git](https://git-scm.org),
 | 
			
		||||
[sbt](https://scala-sbt.org), [Elm](https://elm-lang.org) and
 | 
			
		||||
[nodejs](https://www.npmjs.com/get-npm) (for the `npm` command) to
 | 
			
		||||
compile and run the project.
 | 
			
		||||
 | 
			
		||||
It is also recommended to install `elm-format` as it will help you to
 | 
			
		||||
format the elm source code. Look
 | 
			
		||||
[here](https://github.com/avh4/elm-format) for how to install it with
 | 
			
		||||
your editor of choice.
 | 
			
		||||
 | 
			
		||||
## Checkout the source code
 | 
			
		||||
 | 
			
		||||
Note: These steps are only required to do once. If you come back to
 | 
			
		||||
translating, just start the application.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Use git to clone the docspell repository to your machine. In a
 | 
			
		||||
terminal type:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
❯ git clone https://github.com/eikek/docspell.git
 | 
			
		||||
Cloning into 'docspell'...
 | 
			
		||||
remote: Enumerating objects: 1861, done.
 | 
			
		||||
remote: Counting objects: 100% (1861/1861), done.
 | 
			
		||||
remote: Compressing objects: 100% (861/861), done.
 | 
			
		||||
remote: Total 30276 (delta 821), reused 1604 (delta 668), pack-reused 28415
 | 
			
		||||
Receiving objects: 100% (30276/30276), 60.89 MiB | 23.62 MiB/s, done.
 | 
			
		||||
Resolving deltas: 100% (14658/14658), done.
 | 
			
		||||
 | 
			
		||||
/tmp took 4s
 | 
			
		||||
❯
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This creates a new directory `docspell`. Change into it, create a
 | 
			
		||||
`DOCSPELL_ENV` environment variable and run sbt:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
❯ cd docspell
 | 
			
		||||
docspell on  master via 🌳 v0.19.1 via ☕ v11.0.9 via ⬢ v12.21.0
 | 
			
		||||
❯ export DOCSPELL_ENV=dev
 | 
			
		||||
❯ sbt
 | 
			
		||||
[info] welcome to sbt 1.5.0 (Oracle Corporation Java 1.8.0_212)
 | 
			
		||||
[info] loading settings for project global-plugins from plugins.sbt ...
 | 
			
		||||
[info] loading settings for project docspell-build from plugins.sbt ...
 | 
			
		||||
[info] loading project definition from /tmp/docspell/project
 | 
			
		||||
[info] compiling 6 Scala sources to /tmp/docspell/project/target/scala-2.12/sbt-1.0/classes ...
 | 
			
		||||
[info] loading settings for project root from build.sbt,version.sbt ...
 | 
			
		||||
[info] resolving key references (24191 settings) ...
 | 
			
		||||
[info] set current project to docspell-root (in build file:/tmp/docspell/)
 | 
			
		||||
[info] sbt server started at local:///home/eike/.sbt/1.0/server/3cf61b9ad9af43ee6032/sock
 | 
			
		||||
[info] started sbt server
 | 
			
		||||
sbt:docspell-root>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This downloads some stuff and puts you in the sbt shell. Now compile
 | 
			
		||||
everything (only needed the first time after checkout):
 | 
			
		||||
 | 
			
		||||
``` sbt
 | 
			
		||||
sbt:docspell-root> make
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will take a while, you need to wait until this is finished.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Start the application
 | 
			
		||||
 | 
			
		||||
If sbt is not started, start sbt from within the source root. Also
 | 
			
		||||
export the `DOCSPELL_ENV` variable *before* starting sbt:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
> export DOCSPELL_ENV=dev
 | 
			
		||||
> sbt
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then start the application:
 | 
			
		||||
 | 
			
		||||
``` sbt
 | 
			
		||||
sbt:docspell-root> reStart
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This starts docspell (joex and the restserver). Once the output gets a
 | 
			
		||||
bit quiter, open a browser and navigate to `http://localhost:7880`.
 | 
			
		||||
You can create a new account (if not already done so) and login.
 | 
			
		||||
 | 
			
		||||
Note that the database is created in your `/tmp` directory, so it
 | 
			
		||||
might be cleared once you restart your machine. For translating this
 | 
			
		||||
should not be a problem.
 | 
			
		||||
 | 
			
		||||
## Make webui updates faster
 | 
			
		||||
 | 
			
		||||
The sbt build tool could be used to watch the elm sources and
 | 
			
		||||
re-compile everything on change. This however also restarts the server
 | 
			
		||||
and takes quite long. When only coding on the webui the server can be
 | 
			
		||||
just left as is. Only the new compiled webapp must be made available
 | 
			
		||||
to the running server. For this, a script is provided in the
 | 
			
		||||
`project/` folder.
 | 
			
		||||
 | 
			
		||||
Now open another terminal and `cd` into the docspell folder as before
 | 
			
		||||
and run the following:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
❯ ./project/dev-ui-build.sh watch
 | 
			
		||||
Compile elm to js …
 | 
			
		||||
Success!
 | 
			
		||||
 | 
			
		||||
    Main ───> /tmp/docspell/modules/webapp/target/scala-2.13/classes/META-INF/resources/webjars/docspell-webapp/0.22.0-SNAPSHOT/docspell-app.js
 | 
			
		||||
 | 
			
		||||
Building css …
 | 
			
		||||
/tmp/docspell
 | 
			
		||||
Watching css and elm sources. C-c to quit.
 | 
			
		||||
Setting up watches.  Beware: since -r was given, this may take a while!
 | 
			
		||||
Watches established.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Once you see this, you're all set. The docspell application is running
 | 
			
		||||
and changes to elm files are detected, the webapp is compiled and the
 | 
			
		||||
resulting javascript file is copied to the correct location. To see
 | 
			
		||||
your changes, a refresh in the browser is necessary.
 | 
			
		||||
 | 
			
		||||
If this script is not working, install inotify-tools. The
 | 
			
		||||
`inotifywait` command is required.
 | 
			
		||||
 | 
			
		||||
You'll notice that compiling elm files is very fast!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Find the webapp sources
 | 
			
		||||
 | 
			
		||||
The web-ui is implemented in the `webapp` module. The sources can be
 | 
			
		||||
found in the folder `modules/webapp/src/main/elm`.
 | 
			
		||||
 | 
			
		||||
All translated strings are in the files below `Messages` directory.
 | 
			
		||||
You should start with the file `UiLanguage.elm` to add a new language
 | 
			
		||||
to the list. Then start with `App.elm` to provide transalations. See
 | 
			
		||||
below for details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Example: Add German
 | 
			
		||||
 | 
			
		||||
## Add the new language
 | 
			
		||||
 | 
			
		||||
Start by editing `UiLanguage.elm` and add another language to the
 | 
			
		||||
list:
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
type UiLanguage
 | 
			
		||||
    = English
 | 
			
		||||
    | German
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
More languaes are simply appended using the `|` symbol. Use the
 | 
			
		||||
English name here, because this is source code.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Also add it to the list of all languages below. Simply add the new
 | 
			
		||||
language separated by a comma `,`.
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
all : List UiLanguage
 | 
			
		||||
all =
 | 
			
		||||
    [ English
 | 
			
		||||
    , German
 | 
			
		||||
    ]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you make a mistake, the elm compiler will tell you with usually
 | 
			
		||||
quite helpful messages. Now, after adding this, there will be errors
 | 
			
		||||
when compiling the elm files. You should see something like this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
Detected problems in 1 module.
 | 
			
		||||
-- MISSING PATTERNS ------------------- modules/webapp/src/main/elm/Messages.elm
 | 
			
		||||
 | 
			
		||||
This `case` does not have branches for all possibilities:
 | 
			
		||||
 | 
			
		||||
45|>    case lang of
 | 
			
		||||
46|>        English ->
 | 
			
		||||
47|>            gb
 | 
			
		||||
 | 
			
		||||
Missing possibilities include:
 | 
			
		||||
 | 
			
		||||
    German
 | 
			
		||||
 | 
			
		||||
I would have to crash if I saw one of those. Add branches for them!
 | 
			
		||||
 | 
			
		||||
Hint: If you want to write the code for each branch later, use `Debug.todo` as a
 | 
			
		||||
placeholder. Read <https://elm-lang.org/0.19.1/missing-patterns> for more
 | 
			
		||||
guidance on this workflow.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
So around line 45 in `Messages.elm` there is something wrong. This is
 | 
			
		||||
the place where a record of all strings is returned given some
 | 
			
		||||
lanugage. Currently, there is only one set of strings for English.
 | 
			
		||||
Open this file, you see at the and a value of name `gb` for English.
 | 
			
		||||
Copy it to another name, `de` for this example (it's good practice to
 | 
			
		||||
stick to the two letter country code).
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
de : Messages
 | 
			
		||||
de =
 | 
			
		||||
    { lang = German
 | 
			
		||||
    , iso2 = "de"
 | 
			
		||||
    , label = "Deutsch"
 | 
			
		||||
    , flagIcon = "flag-icon flag-icon-de"
 | 
			
		||||
    , app = Messages.App.gb
 | 
			
		||||
    , collectiveSettings = Messages.Page.CollectiveSettings.gb
 | 
			
		||||
    , login = Messages.Page.Login.gb
 | 
			
		||||
    , register = Messages.Page.Register.gb
 | 
			
		||||
    , newInvite = Messages.Page.NewInvite.gb
 | 
			
		||||
    , upload = Messages.Page.Upload.gb
 | 
			
		||||
    , itemDetail = Messages.Page.ItemDetail.gb
 | 
			
		||||
    , queue = Messages.Page.Queue.gb
 | 
			
		||||
    , userSettings = Messages.Page.UserSettings.gb
 | 
			
		||||
    , manageData = Messages.Page.ManageData.gb
 | 
			
		||||
    , home = Messages.Page.Home.gb
 | 
			
		||||
    }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Change `lang`, `iso2`, `label` and `flagIcon` appropriately. For the
 | 
			
		||||
`label` use the native language name (not English), as this is the
 | 
			
		||||
label shown to users when selecting a language. The flag icon can be
 | 
			
		||||
copied and only the last two letters need to be changed to the country
 | 
			
		||||
code. You may look [here](https://github.com/lipis/flag-icon-css) for
 | 
			
		||||
additional information.
 | 
			
		||||
 | 
			
		||||
Now the error can be fixed. Go to line 45 and add another branch to
 | 
			
		||||
the `case` expression:
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
get : UiLanguage -> Messages
 | 
			
		||||
get lang =
 | 
			
		||||
    case lang of
 | 
			
		||||
        English ->
 | 
			
		||||
            gb
 | 
			
		||||
 | 
			
		||||
        German ->
 | 
			
		||||
            de
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This makes the compiler happy again. If you refresh the browser, you
 | 
			
		||||
should see the new language in the dropdown menu. You can already
 | 
			
		||||
choose the new language, but nothing happens in the application. Of
 | 
			
		||||
course, we just copied the English strings for now. So now begins the
 | 
			
		||||
translation process.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Translating
 | 
			
		||||
 | 
			
		||||
Now translation can begin. If you look at the newly created value
 | 
			
		||||
`de`, you'll see some entries in the record. Each corresponds to a
 | 
			
		||||
page: `login` is for the login page, `home` for the "home page" etc;
 | 
			
		||||
and `app` is for the top menu.
 | 
			
		||||
 | 
			
		||||
Take one of them and start translating. For the example, I use the
 | 
			
		||||
first one which is `Messages.App`. The file to this is
 | 
			
		||||
`Messages/App.em`. You can always replace the dots with slashes to
 | 
			
		||||
find a file to an elm module. Open this file and you'll see again a
 | 
			
		||||
`gb` value at the end. Copy it to `de` and start translating:
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
de : Texts
 | 
			
		||||
de =
 | 
			
		||||
    { collectiveProfile = "Kollektiv-Profil"
 | 
			
		||||
    , userProfile = "Benutzer-Profil"
 | 
			
		||||
    , lightDark = "Hell/Dunkel"
 | 
			
		||||
    , logout = "Abmelden"
 | 
			
		||||
    , items = "Dokumente"
 | 
			
		||||
    , manageData = "Daten verwalten"
 | 
			
		||||
    , uploadFiles = "Dateien hochladen"
 | 
			
		||||
    , processingQueue = "Verarbeitung"
 | 
			
		||||
    , newInvites = "Neue Einladung"
 | 
			
		||||
    , help = "Hilfe (English)"
 | 
			
		||||
    }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then go to the beginning of the file and add the new `de` value to the
 | 
			
		||||
list of "exposed" values. This is necessary so it can be used from
 | 
			
		||||
within the `Messages.elm` module.
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
module Messages.App exposing
 | 
			
		||||
    ( Texts
 | 
			
		||||
    , de {- the new value -}
 | 
			
		||||
    , gb
 | 
			
		||||
    )
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Now you can go back to `Messages.elm` and exchange `Messages.App.gb`
 | 
			
		||||
with `Messages.App.de`.
 | 
			
		||||
 | 
			
		||||
``` elm
 | 
			
		||||
de : Messages
 | 
			
		||||
de =
 | 
			
		||||
    { lang = German
 | 
			
		||||
    , iso2 = "de"
 | 
			
		||||
    , label = "Deutsch"
 | 
			
		||||
    , flagIcon = "flag-icon flag-icon-de"
 | 
			
		||||
    , app = Messages.App.de
 | 
			
		||||
    , collectiveSettings = Messages.Page.CollectiveSettings.gb
 | 
			
		||||
    , login = Messages.Page.Login.gb
 | 
			
		||||
    , register = Messages.Page.Register.gb
 | 
			
		||||
    , newInvite = Messages.Page.NewInvite.gb
 | 
			
		||||
    , upload = Messages.Page.Upload.gb
 | 
			
		||||
    , itemDetail = Messages.Page.ItemDetail.gb
 | 
			
		||||
    , queue = Messages.Page.Queue.gb
 | 
			
		||||
    , userSettings = Messages.Page.UserSettings.gb
 | 
			
		||||
    , manageData = Messages.Page.ManageData.gb
 | 
			
		||||
    , home = Messages.Page.Home.gb
 | 
			
		||||
    }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you refresh the browser, you should now see the new values. Then
 | 
			
		||||
take the next entry and start over. It happens that some files contain
 | 
			
		||||
other string-sets of certain components. Then just follow this guide
 | 
			
		||||
recursively.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Publishing
 | 
			
		||||
 | 
			
		||||
You can publish your work to this repo in various ways:
 | 
			
		||||
 | 
			
		||||
## Github PR
 | 
			
		||||
 | 
			
		||||
This is the preferred way, because it means less work for me :). If
 | 
			
		||||
you have a github account, you can create a pull request. Here is a
 | 
			
		||||
quick walk-through. There is a thorough help [at
 | 
			
		||||
github](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests).
 | 
			
		||||
 | 
			
		||||
1. Fork this repository in the github webapp
 | 
			
		||||
2. Go to the docspell source root you checked out in the terminal. Run:
 | 
			
		||||
   ```
 | 
			
		||||
   git remote rename origin upstream
 | 
			
		||||
   git remote add origin git@github.com:<your-github-name>/docspell.git
 | 
			
		||||
   git fetch --all
 | 
			
		||||
   ```
 | 
			
		||||
3. Create a new git branch:
 | 
			
		||||
   ```
 | 
			
		||||
   git checkout -b translate origin/master
 | 
			
		||||
   ```
 | 
			
		||||
4. Make a commit of your changes:
 | 
			
		||||
   ```
 | 
			
		||||
   git config user.name "Your Name"
 | 
			
		||||
   git config user.email "Your Email" #(note that this email will be publicly viewable! a dummy address is fine, too)
 | 
			
		||||
   git commit -am 'Add translation for German'
 | 
			
		||||
   ```
 | 
			
		||||
   Modify the message to your needs.
 | 
			
		||||
5. Push the change to your fork:
 | 
			
		||||
   ```
 | 
			
		||||
   git push origin translate
 | 
			
		||||
   ```
 | 
			
		||||
6. Go to the github webapp and create a pull request from your branch.
 | 
			
		||||
 | 
			
		||||
## E-Mail
 | 
			
		||||
 | 
			
		||||
You can send me the patch via e-mail. You can use `git send-email` or
 | 
			
		||||
your favorite e-mail client. For this do step 4 from above and then:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git bundle create translation.bundle origin/master..HEAD
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then send the created `translate.bundle` file. If this command doesn't
 | 
			
		||||
work, try:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git format-patch origin/master..HEAD
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This results in one or more `0001-…` files that you can send.
 | 
			
		||||
 | 
			
		||||
## Any other
 | 
			
		||||
 | 
			
		||||
Contact me by mail or create an issue.
 | 
			
		||||
		Reference in New Issue
	
	Block a user