feat(faqs): i18n

This commit is contained in:
Gregor Kleen 2020-04-24 11:09:14 +02:00
parent 10d44d189b
commit a1a0fa3a44
13 changed files with 224 additions and 46 deletions

View File

@ -1,3 +1,3 @@
FAQNoCampusAccount: Ich habe keinen LMU Campus-Login; kann ich trotzdem Zugang zum System erhalten?
FAQNoCampusAccount: Ich habe keine LMU-Benutzerkennung (ehem. Campus-Kennung); kann ich trotzdem Zugang zum System erhalten?
FAQForgottenPassword: Ich habe mein Passwort vergessen
FAQCampusCantLogin: Ich kann mich mit meinem LMU Campus-Login nicht anmelden
FAQCampusCantLogin: Ich kann mich mit meiner LMU-Benutzerkennung (ehem. Campus-Kennung) nicht anmelden

3
messages/faq/en-eu.msg Normal file
View File

@ -0,0 +1,3 @@
FAQNoCampusAccount: I don't have a LMU user ID (formerly Campus-ID); can I still get access to Uni2work?
FAQForgottenPassword: I have forgotten my password
FAQCampusCantLogin: I can't log in using my LMU user ID (formerly Campus-ID)

View File

@ -1249,6 +1249,7 @@ MenuAllocationUsers: Applicants
MenuAllocationPriorities: Central priorities
MenuAllocationCompute: Compute allocation
MenuAllocationAccept: Accept allocation
MenuFaq: FAQ
BreadcrumbSubmissionFile: File
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
@ -1319,6 +1320,7 @@ BreadcrumbAllocationPriorities: Central priorities
BreadcrumbAllocationCompute: Compute allocation
BreadcrumbAllocationAccept: Accept allocation
BreadcrumbMessageHide: Hide
BreadcrumbFaq: FAQ
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
ExternalExamGrades coursen examn: Exam achievements: #{coursen}, #{examn}
@ -2479,3 +2481,6 @@ BearerTokenExpires: Expiration time
BearerTokenExpiresTip: If no expiration time is given, the token will not expire. It will be valid forever.
BearerTokenOverrideStart: Start time
BearerTokenOverrideStartTip: If no start time is given, only the expiration time will be checked when the token is used.
FaqTitle: Frequently asked questions
AdditionalFaqs: More frequently asked questions

View File

@ -79,11 +79,19 @@ for msgDirectory (${msgDirectories}); do
# printf ">>> %s\n" ${msgDirectory}
if [[ $fix != 0 ]]; then
diff -u0 --suppress-common-lines -wB ${diffArgs} | grep -vE '^@@.*@@'
diffStatus=$pipestatus[0]
if [[ ${#dirMsgFiles} -gt 1 ]]; then
diff -u0 --suppress-common-lines -wB ${diffArgs} | grep -vE '^@@.*@@'
diffStatus=$pipestatus[0]
else
diffStatus=1
fi
else
diff -u0 --suppress-common-lines -wB ${diffArgs} >/dev/null
diffStatus=$?
if [[ ${#dirMsgFiles} -gt 1 ]]; then
diff -u0 --suppress-common-lines -wB ${diffArgs} >/dev/null
diffStatus=$?
else
diffStatus=1
fi
if [[ ${diffStatus} == 1 ]]; then
./translate.hs msgs ${dirMsgFiles} && diffStatus=0
@ -118,13 +126,18 @@ for templateDirectory (templates/i18n/**/*(FN)); do
for ext (${templateExtensions}); do
for lang (${requiredLangs}); do
# printf ">> %s %s\n" ${ext} ${lang}
foundLang=0
for templateFile (${templateDirectory}/*.${ext}); do
[[ ${templateFile:t} =~ "(^|.)${lang}[-.]" ]] || continue
# printf "%s\n" ${templateFile}
[[ ${templateFile:t} =~ "(^|\.)${lang}[-.]" ]] || continue
foundLang=1
break
done
# printf ">> %s\n" ${foundLang}
if [[ $foundLang -ne 1 ]]; then
templateDifference=1
[[ $fix != 0 ]] && printf "%s: %s (%s)\n" $templateDirectory $lang $ext

View File

@ -1,5 +1,12 @@
$newline never
<dl .deflist>
<dt .deflist__dt>
^{formatGregorianW 2020 04 24}
<dd .deflist__dd>
<ul>
<li>
Häufig gestellte Fragen
<dt .deflist__dt>
^{formatGregorianW 2020 04 17}
<dd .deflist__dd>

View File

@ -1,5 +1,12 @@
$newline never
<dl .deflist>
<dt .deflist__dt>
^{formatGregorianW 2020 04 24}
<dd .deflist__dd>
<ul>
<li>
Frequently asked questions
<dt .deflist__dt>
^{formatGregorianW 2020 04 17}
<dd .deflist__dd>

View File

@ -6,9 +6,9 @@ $newline never
im <a href="https://www.portal.uni-muenchen.de">Campus-Portal</a> #
anmelden?<br />
Falls nicht ist davon auszugehen, dass Sie Ihre Anmeldedaten falsch #
eingeben oder <a href=^{faqLink FAQNoCampusAccount}>keinen #
Campus-Login besitzen</a>.
Falls nicht, ist davon auszugehen, dass Sie Ihre Anmeldedaten falsch #
eingeben oder <a href=^{faqLink FAQNoCampusAccount}>keine #
LMU-Benutzerkennung (ehem. Campus-Kennung) besitzen</a>.
<p>
Beachten Sie dabei auch, dass Uni2work Leerzeichen sowohl im #
@ -19,8 +19,8 @@ $newline never
<p>
Uni2work bietet zwei Login-Formulare.<br />
Für die Anmeldung mit der LMU Campus-Kennung müssen Sie das Formular #
„Campus-Login“ verwenden.
Für die Anmeldung mit der LMU-Benutzerkennung (ehem. Campus-Kennung) #
müssen Sie das Formular „Campus-Login“ verwenden.
<p>
Falls Sie sich #

View File

@ -0,0 +1,33 @@
$newline never
<p>
Can you log in to #
the <a href="https://www.portal.uni-muenchen.de">Campus-Portal</a> #
using the <i>exact same</i> (ideally copied & pasted) login data?
<br>
If you cannot you can assume that you are entering your login data #
wrong or do that you <a href=^{faqLink FAQNoCampusAccount}>do not #
have a LMU user ID (formerly Campus-ID)</a>.
<p>
Please consider that for Uni2work both your user ID and password are #
sensitive to whitespace characters.
<br>
Your password is also case-sensitive.
<p>
Uni2work offers to login forms.
<br>
To log in using your LMU user ID (formerly Campus-ID) you need to #
use the form titled “Campus login”.
<p>
If you can log in to #
the <a href="https://www.portal.uni-muenchen.de">Campus-Portal</a> #
but can't log in to Uni2work, please contact a #
Uni2work-Administrator using the <a href=@{HelpR}>Support form</a> #
(at the top right of every page).

View File

@ -1,12 +1,22 @@
$newline never
<p>
Wenn Sie sich gewöhnlicherweise mit Ihrem LMU Campus-Login anmelden, #
wenden Sie sich bitte an #
den <a href="https://www.it-servicedesk.uni-muenchen.de">IT-Servicedesk</a> #
Wenn Sie sich gewöhnlicherweise mit Ihrer LMU-Benutzerkennug #
(ehem. Campus-Kennung) anmelden, wenden Sie sich bitte an #
den <a href="https://www.it-servicedesk.uni-muenchen.de/faq/index.html#campuskennung-passwort-vergessen">IT-Servicedesk</a> #
um Ihr Passwort zurücksetzen zu lassen.
<p>
Wenn Sie sich mit einer Uni2work-internen Kennung anmelden wenden #
Sie sich dafür bitte über das <a href=@{HelpR}>Hilfe-Formular</a>, #
oben rechts auf jeder Seite, an die Uni2work-Administration.
Sie sich dafür bitte über das <a href=@{HelpR}>Hilfe-Formular</a> #
(oben rechts auf jeder Seite) an die Uni2work-Administration.
<br>
Tragen sie dabei unter „Antworten an“ die Adresse ein, an die #
Uni2work gewöhnlicherweise Mitteilungen verschickt.
<br>
Bitte geben Sie zusätzlich mind. eine nicht-öffentliche #
personenbezogene Information an, um den Administratoren zu helfen #
die Anfrage zu authorisieren. #
Geeignet ist z.B. die Matrikelnummer oder der ungefähre Zeitpunkt #
des letzten Logins.

View File

@ -0,0 +1,21 @@
$newline never
<p>
If you usually log in using your LMU user ID (formerly Campus-ID) #
please contact #
the <a href="https://www.it-servicedesk.uni-muenchen.de/faq/index.html#campuskennung-passwort-vergessen">IT #
servicedesk (german)</a> to reset your password.
<p>
If you log in using a Uni2work-internal account please use #
the <a href=@{HelpR}>Support form</a> (at the top right of every #
page) to contact a Uni2work-administrator.
<br>
Specify the email to which Uni2work usually sends notifications #
under “Send answers to”.
<br>
Please also include at least one non-public piece of information to #
help authorise your request. #
We suggest your Matriculation number or the approximate time of your #
last successful login.

View File

@ -24,12 +24,15 @@ $newline never
<dt>Vollständiger Name
<dd>Der vollständige Name muss mindestens den kompletten Nachnamen enthalten
<dd>Der vollständige Name kann zudem beliebige Teile der Vornamen und des akademischen Titels enthalten
<dt>E-Mail Addresse zur Anzeige
<dd>Wird anderen Benutzern angezeigt, wenn man z.B. als Kursverwalter oder Korrektor eingetragen ist
<dd>So wird der Name anderen Benutzern angezeigt
<dt>Matrikelnummer
<dt>Geschlecht
<dd>„Unbekannt“, „Männlich“, „Weiblich“ oder „Keine Angabe“
<dd>Nach <a href="https://en.wikipedia.org/wiki/ISO/IEC_5218">ISO 5218</a>
<dt>E-Mail Addresse zum Versand
<dd>An diese Addresse werden Mitteilungen von Uni2work versandt
$# <dd>Nach <a href="https://en.wikipedia.org/wiki/ISO/IEC_5218">ISO 5218</a>
<dt>E-Mail Adresse zur Anzeige
<dd>Wird öffentlich angezeigt, wenn man z.B. als Kursverwalter oder Korrektor eingetragen ist
<dd>Kursverwalter von Kursen, in denen man Teilnehmer ist, sehen die E-Mail Adresse zum Versand
<dt>E-Mail Adresse zum Versand
<dd>An diese Adresse werden Mitteilungen von Uni2work versandt
<dd>Die zuverlässige Zustellung muss gewährleistet sein, daher keine Emails von freien Mailanbietern wie GMail, Hotmail, GMX, etc.
<dd>Bei externen Studierenden sollte die E-Mail Adresse der externen Institution verwendet werden, z.B. <code>@mytum.de</code> für TUM-Studierende

View File

@ -0,0 +1,35 @@
$newline never
<p>
Uni2work-administrators can create Uni2work-internal accounts.
<p>
Please use the <a href=@{HelpR}>Support form</a> (at the top right #
of every page) to contact a Uni2work-administrator.
<p>
Explain your situation and provide a reason for requiring access to #
Uni2work.
<p>
Please send the following information with your request:
<dl .deflist--no-grid>
<dt>Academic title
<dt>Given name(s)
<dt>Full surname
<dd>The surname may consist of multiple words
<dt>Full name
<dd>The full name must contain the complete surname
<dd>The full name may also contain arbitrary components of the given name(s) and academic title
<dt>Matriculation number
<dt>Sex
<dd>“Not known”, “Male”, “Female”, or “Not specified”
<dt>Email address for display
<dd>This email address is published if you are for example a course administrator or corrector
<dd>Course administrators for courses in which you participate are shown the email address for sending
<dt>Email address for sending
<dd>Uni2work sends notifications to this address
<dd>Reliable delivery of email must be ensured. Therefore free mail hosters like GMail, Hotmail, GMX, etc. are not permitted
<dd>For external students the email address provided by their institution should be used, e.g. <code>@mytum.de</code> for TUM-students

View File

@ -52,6 +52,7 @@ import System.Process
import System.IO
import System.Exit
import System.IO.Temp (withSystemTempFile, writeSystemTempFile)
import System.IO.Error
import Data.Ord (Down(..))
@ -61,6 +62,8 @@ import Control.Monad.Catch
data Translate
= TranslateMsgs
{ msgFiles :: [FilePath]
, msgOnlyLang :: Bool
, msgRequiredLangs :: [String]
}
| TranslateI18nDirectory
{ i18nDir :: FilePath
@ -74,21 +77,28 @@ $(cmdArgsQuote [d|
messages = TranslateMsgs
{ msgFiles = [] &=# args
&=# typFile
, msgOnlyLang = True
&=# name "only-lang"
&=# help "Should only the language compononent (en, de, ...) be considered?"
, msgRequiredLangs = []
&=# name "required"
&=# help "Which languages are required to exist?"
&=# typ "LANG"
}
i18n = TranslateI18nDirectory
{ i18nDir = def &=# argPos 0
&=# typDir
, i18nOnlyLang = True
&=# name "only-lang"
&=# help "Should only the language compononent (en, de, ...) be considered?"
&=# name "only-lang"
&=# help "Should only the language compononent (en, de, ...) be considered?"
, i18nRequiredLangs = []
&=# name "required"
&=# help "Which languages are required to exist?"
&=# typ "LANG"
, i18nSourceLangs = []
&=# name "source"
&=# help "Preference order for source of translation"
&=# name "required"
&=# help "Which languages are required to exist?"
&=# typ "LANG"
, i18nSourceLangs = []
&=# name "source"
&=# help "Preference order for source of translation"
&=# typ "LANG"
}
run = cmdArgs# (modes# [ messages &=# auto &=# name "msgs"
@ -118,18 +128,22 @@ data MsgFile = MsgFile
main :: IO ()
main = main' =<< run
where
main' TranslateMsgs{..} = do
let
filePairs :: [(FilePath, FilePath)]
filePairs = concat $ zipWith (fmap . (,)) msgFiles (tail $ tails msgFiles)
mapM_ (\(f1, f2) -> join $ combine <$> readMsgFile f1 <*> readMsgFile f2) filePairs
main' m@TranslateMsgs{..}
| null msgRequiredLangs = main' m{ msgRequiredLangs = ["de-de-formal", "en-eu"] }
| otherwise = do
msgFiles' <- nub . (msgFiles ++) <$> getMissingFiles m
let
filePairs :: [(FilePath, FilePath)]
filePairs = concat $ zipWith (fmap . (,)) msgFiles (tail $ tails msgFiles')
mapM_ (\(f1, f2) -> join $ combine <$> readMsgFile f1 <*> readMsgFile f2) filePairs
main' m@TranslateI18nDirectory{..}
| null i18nRequiredLangs = main' m{ i18nRequiredLangs = ["de-de-formal", "en-eu"] }
| null i18nSourceLangs = main' m{ i18nSourceLangs = ["de-de-formal"] }
| otherwise = do
missing <- getMissingFiles m
forM_ missing $ \missing' -> do
translateSource <- getTranslateSource m
translateSource <- getTranslateSource m missing'
case translateSource of
Just src -> translateFrom src missing'
Nothing -> do
@ -138,7 +152,8 @@ main = main' =<< run
readMsgFile :: FilePath -> IO MsgFile
readMsgFile f = readMsgText f <$> Text.readFile f
readMsgFile f = catchIf isDoesNotExistError readMsgFile' . const . return $ MsgFile f mempty mempty
where readMsgFile' = readMsgText f <$> Text.readFile f
readMsgText :: FilePath -> Text -> MsgFile
readMsgText f (Text.lines -> ls) =
@ -184,10 +199,11 @@ renderMsg MsgDefinition{..} = (<> (": " <> msgTrans)) . Text.unwords $
insertIntoFile :: MsgFile -> MsgFile -> MsgFile -> IO ()
insertIntoFile target reference source = do
let getLines = fmap (P.fromListEnd . Text.lines) . Text.readFile
forM_ (msgDefinitions source) $ \msgDef -> do
targetLines <- P.fromListEnd . Text.lines <$> Text.readFile (msgFile target)
referenceLines <- P.fromListEnd . Text.lines <$> Text.readFile (msgFile reference)
targetLines <- catchIf isDoesNotExistError (getLines $ msgFile target) . const $ return Nothing
referenceLines <- getLines $ msgFile reference
case toList <$> targetLines of
Just lines -> do
@ -265,18 +281,29 @@ normalizeLang onlyLang
| otherwise = id
getLang :: Bool -> FilePath -> String
getLang onlyLang = normalizeLang onlyLang . takeFileName
getLang onlyLang = normalizeLang onlyLang . Text.unpack . last . Text.splitOn "." . Text.pack . dropExtension . takeFileName
replaceLang :: FilePath -> String -> FilePath
replaceLang reference l = takeDirectory reference </> l <.> takeExtensions reference
replaceLang reference l = takeDirectory reference </> withPrefix l <.> takeExtension reference
where prefix = getPrefix reference
withPrefix | not $ null prefix = (prefix <.>)
| otherwise = id
getPrefix :: FilePath -> String
getPrefix = Text.unpack . Text.intercalate "." . init . Text.splitOn "." . Text.pack . dropExtension . takeFileName
getFiles :: FilePath -> IO [FilePath]
getFiles dir = filterM doesFileExist . map (dir </>) =<< listDirectory dir
getTranslateSource :: Translate -> IO (Maybe FilePath)
getTranslateSource TranslateI18nDirectory{..} = do
getTranslateSource :: Translate -> FilePath -> IO (Maybe FilePath)
getTranslateSource TranslateI18nDirectory{..} missing = do
fs <- getFiles i18nDir
let fs' = sortOn (\(getLang i18nOnlyLang -> l) -> Down . elemIndex l . reverse $ map (normalizeLang i18nOnlyLang) i18nSourceLangs) fs
let fs' = sortOn (\(getLang i18nOnlyLang -> l) -> Down . elemIndex l . reverse $ map (normalizeLang i18nOnlyLang) i18nSourceLangs)
[ f
| f <- fs
, getPrefix f == getPrefix missing
, takeExtension f == takeExtension missing
]
return $ listToMaybe fs'
getMissingFiles :: Translate -> IO [FilePath]
@ -284,8 +311,8 @@ getMissingFiles TranslateI18nDirectory{..} = do
fs <- getFiles i18nDir
let
exts :: HashMap String [FilePath]
exts = HashMap.fromListWith (<>) $ map (takeExtensions &&& pure) fs
exts :: HashMap (String, String) [FilePath]
exts = HashMap.fromListWith (<>) $ map ((getPrefix &&& takeExtension) &&& pure) fs
return . flip concatMap exts $ \refs@(r : _) ->
let ls :: [String]
@ -293,6 +320,20 @@ getMissingFiles TranslateI18nDirectory{..} = do
missing :: [String]
missing = filter (\l -> not $ any (== normalizeLang i18nOnlyLang l) ls) i18nRequiredLangs
in map (replaceLang r) missing
getMissingFiles TranslateMsgs{..} = do
fs <- concat <$> mapM getFiles (map takeDirectory msgFiles)
let
exts :: HashMap String [FilePath]
exts = HashMap.fromListWith (<>) $ map (takeExtension &&& pure) fs
return . flip concatMap exts $ \refs@(r : _) ->
let ls :: [String]
ls = map (getLang msgOnlyLang) refs
missing :: [String]
missing = filter (\l -> not $ any (== normalizeLang msgOnlyLang l) ls) msgRequiredLangs
in map (replaceLang r) missing
translateFrom :: FilePath -> FilePath -> IO ()
translateFrom from to = do