From a1a0fa3a448c75f83949eb9f3a5f681fcd6e5792 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 24 Apr 2020 11:09:14 +0200 Subject: [PATCH] feat(faqs): i18n --- messages/faq/de-de-formal.msg | 4 +- messages/faq/en-eu.msg | 3 + messages/uniworx/en-eu.msg | 5 ++ missing-translations.sh | 23 +++-- templates/i18n/changelog/de-de-formal.hamlet | 7 ++ templates/i18n/changelog/en-eu.hamlet | 7 ++ .../faq/campus-cant-login.de-de-formal.hamlet | 10 +-- .../i18n/faq/campus-cant-login.en-eu.hamlet | 33 +++++++ .../forgotten-password.de-de-formal.hamlet | 20 +++-- .../i18n/faq/forgotten-password.en-eu.hamlet | 21 +++++ .../faq/no-campus-account.de-de-formal.hamlet | 13 +-- .../i18n/faq/no-campus-account.en-eu.hamlet | 35 ++++++++ translate.hs | 89 ++++++++++++++----- 13 files changed, 224 insertions(+), 46 deletions(-) create mode 100644 messages/faq/en-eu.msg create mode 100644 templates/i18n/faq/campus-cant-login.en-eu.hamlet create mode 100644 templates/i18n/faq/forgotten-password.en-eu.hamlet create mode 100644 templates/i18n/faq/no-campus-account.en-eu.hamlet diff --git a/messages/faq/de-de-formal.msg b/messages/faq/de-de-formal.msg index 5491fec9f..c8f5976fe 100644 --- a/messages/faq/de-de-formal.msg +++ b/messages/faq/de-de-formal.msg @@ -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 \ No newline at end of file +FAQCampusCantLogin: Ich kann mich mit meiner LMU-Benutzerkennung (ehem. Campus-Kennung) nicht anmelden \ No newline at end of file diff --git a/messages/faq/en-eu.msg b/messages/faq/en-eu.msg new file mode 100644 index 000000000..98cfc6b1e --- /dev/null +++ b/messages/faq/en-eu.msg @@ -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) diff --git a/messages/uniworx/en-eu.msg b/messages/uniworx/en-eu.msg index c66f2cdd2..3fc27849b 100644 --- a/messages/uniworx/en-eu.msg +++ b/messages/uniworx/en-eu.msg @@ -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 diff --git a/missing-translations.sh b/missing-translations.sh index 8206fe5fc..cd061c6a5 100755 --- a/missing-translations.sh +++ b/missing-translations.sh @@ -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 diff --git a/templates/i18n/changelog/de-de-formal.hamlet b/templates/i18n/changelog/de-de-formal.hamlet index 2d4d809cc..657f619fe 100644 --- a/templates/i18n/changelog/de-de-formal.hamlet +++ b/templates/i18n/changelog/de-de-formal.hamlet @@ -1,5 +1,12 @@ $newline never
+
+ ^{formatGregorianW 2020 04 24} +
+
    +
  • + Häufig gestellte Fragen +
    ^{formatGregorianW 2020 04 17}
    diff --git a/templates/i18n/changelog/en-eu.hamlet b/templates/i18n/changelog/en-eu.hamlet index 8544a57e1..ff5370417 100644 --- a/templates/i18n/changelog/en-eu.hamlet +++ b/templates/i18n/changelog/en-eu.hamlet @@ -1,5 +1,12 @@ $newline never
    +
    + ^{formatGregorianW 2020 04 24} +
    +
      +
    • + Frequently asked questions +
      ^{formatGregorianW 2020 04 17}
      diff --git a/templates/i18n/faq/campus-cant-login.de-de-formal.hamlet b/templates/i18n/faq/campus-cant-login.de-de-formal.hamlet index 9caa83b79..1a4666f48 100644 --- a/templates/i18n/faq/campus-cant-login.de-de-formal.hamlet +++ b/templates/i18n/faq/campus-cant-login.de-de-formal.hamlet @@ -6,9 +6,9 @@ $newline never im Campus-Portal # anmelden?
      - Falls nicht ist davon auszugehen, dass Sie Ihre Anmeldedaten falsch # - eingeben oder keinen # - Campus-Login besitzen. + Falls nicht, ist davon auszugehen, dass Sie Ihre Anmeldedaten falsch # + eingeben oder keine # + LMU-Benutzerkennung (ehem. Campus-Kennung) besitzen.

      Beachten Sie dabei auch, dass Uni2work Leerzeichen sowohl im # @@ -19,8 +19,8 @@ $newline never

      Uni2work bietet zwei Login-Formulare.
      - 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.

      Falls Sie sich # diff --git a/templates/i18n/faq/campus-cant-login.en-eu.hamlet b/templates/i18n/faq/campus-cant-login.en-eu.hamlet new file mode 100644 index 000000000..6ab25f1eb --- /dev/null +++ b/templates/i18n/faq/campus-cant-login.en-eu.hamlet @@ -0,0 +1,33 @@ +$newline never + +

      + + Can you log in to # + the Campus-Portal # + using the exact same (ideally copied & pasted) login data? +
      + + If you cannot you can assume that you are entering your login data # + wrong or do that you do not # + have a LMU user ID (formerly Campus-ID). + +

      + + Please consider that for Uni2work both your user ID and password are # + sensitive to whitespace characters. +
      + Your password is also case-sensitive. + +

      + Uni2work offers to login forms. +
      + To log in using your LMU user ID (formerly Campus-ID) you need to # + use the form titled “Campus login”. + +

      + + If you can log in to # + the Campus-Portal # + but can't log in to Uni2work, please contact a # + Uni2work-Administrator using the Support form # + (at the top right of every page). diff --git a/templates/i18n/faq/forgotten-password.de-de-formal.hamlet b/templates/i18n/faq/forgotten-password.de-de-formal.hamlet index 27001dcbc..be29cb977 100644 --- a/templates/i18n/faq/forgotten-password.de-de-formal.hamlet +++ b/templates/i18n/faq/forgotten-password.de-de-formal.hamlet @@ -1,12 +1,22 @@ $newline never

      - Wenn Sie sich gewöhnlicherweise mit Ihrem LMU Campus-Login anmelden, # - wenden Sie sich bitte an # - den IT-Servicedesk # + Wenn Sie sich gewöhnlicherweise mit Ihrer LMU-Benutzerkennug # + (ehem. Campus-Kennung) anmelden, wenden Sie sich bitte an # + den IT-Servicedesk # um Ihr Passwort zurücksetzen zu lassen.

      Wenn Sie sich mit einer Uni2work-internen Kennung anmelden wenden # - Sie sich dafür bitte über das Hilfe-Formular, # - oben rechts auf jeder Seite, an die Uni2work-Administration. + Sie sich dafür bitte über das Hilfe-Formular # + (oben rechts auf jeder Seite) an die Uni2work-Administration. +
      + Tragen sie dabei unter „Antworten an“ die Adresse ein, an die # + Uni2work gewöhnlicherweise Mitteilungen verschickt. +
      + 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. diff --git a/templates/i18n/faq/forgotten-password.en-eu.hamlet b/templates/i18n/faq/forgotten-password.en-eu.hamlet new file mode 100644 index 000000000..fb42bf6df --- /dev/null +++ b/templates/i18n/faq/forgotten-password.en-eu.hamlet @@ -0,0 +1,21 @@ +$newline never + +

      + If you usually log in using your LMU user ID (formerly Campus-ID) # + please contact # + the IT # + servicedesk (german) to reset your password. + +

      + If you log in using a Uni2work-internal account please use # + the Support form (at the top right of every # + page) to contact a Uni2work-administrator. +
      + Specify the email to which Uni2work usually sends notifications # + under “Send answers to”. +
      + + 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. diff --git a/templates/i18n/faq/no-campus-account.de-de-formal.hamlet b/templates/i18n/faq/no-campus-account.de-de-formal.hamlet index 74710d329..97e2c91d8 100644 --- a/templates/i18n/faq/no-campus-account.de-de-formal.hamlet +++ b/templates/i18n/faq/no-campus-account.de-de-formal.hamlet @@ -24,12 +24,15 @@ $newline never

      Vollständiger Name
      Der vollständige Name muss mindestens den kompletten Nachnamen enthalten
      Der vollständige Name kann zudem beliebige Teile der Vornamen und des akademischen Titels enthalten -
      E-Mail Addresse zur Anzeige -
      Wird anderen Benutzern angezeigt, wenn man z.B. als Kursverwalter oder Korrektor eingetragen ist +
      So wird der Name anderen Benutzern angezeigt
      Matrikelnummer
      Geschlecht
      „Unbekannt“, „Männlich“, „Weiblich“ oder „Keine Angabe“ -
      Nach ISO 5218 -
      E-Mail Addresse zum Versand -
      An diese Addresse werden Mitteilungen von Uni2work versandt +$#
      Nach ISO 5218 +
      E-Mail Adresse zur Anzeige +
      Wird öffentlich angezeigt, wenn man z.B. als Kursverwalter oder Korrektor eingetragen ist +
      Kursverwalter von Kursen, in denen man Teilnehmer ist, sehen die E-Mail Adresse zum Versand +
      E-Mail Adresse zum Versand +
      An diese Adresse werden Mitteilungen von Uni2work versandt
      Die zuverlässige Zustellung muss gewährleistet sein, daher keine Emails von freien Mailanbietern wie GMail, Hotmail, GMX, etc. +
      Bei externen Studierenden sollte die E-Mail Adresse der externen Institution verwendet werden, z.B. @mytum.de für TUM-Studierende diff --git a/templates/i18n/faq/no-campus-account.en-eu.hamlet b/templates/i18n/faq/no-campus-account.en-eu.hamlet new file mode 100644 index 000000000..27f0ac830 --- /dev/null +++ b/templates/i18n/faq/no-campus-account.en-eu.hamlet @@ -0,0 +1,35 @@ +$newline never +

      + + Uni2work-administrators can create Uni2work-internal accounts. + +

      + Please use the Support form (at the top right # + of every page) to contact a Uni2work-administrator. + +

      + Explain your situation and provide a reason for requiring access to # + Uni2work. + +

      + + Please send the following information with your request: + +

      +
      Academic title +
      Given name(s) +
      Full surname +
      The surname may consist of multiple words +
      Full name +
      The full name must contain the complete surname +
      The full name may also contain arbitrary components of the given name(s) and academic title +
      Matriculation number +
      Sex +
      “Not known”, “Male”, “Female”, or “Not specified” +
      Email address for display +
      This email address is published if you are for example a course administrator or corrector +
      Course administrators for courses in which you participate are shown the email address for sending +
      Email address for sending +
      Uni2work sends notifications to this address +
      Reliable delivery of email must be ensured. Therefore free mail hosters like GMail, Hotmail, GMX, etc. are not permitted +
      For external students the email address provided by their institution should be used, e.g. @mytum.de for TUM-students diff --git a/translate.hs b/translate.hs index cc81b6fa4..1494aa82d 100755 --- a/translate.hs +++ b/translate.hs @@ -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