From b009d7a67a5031d071b515cbc8588a384ec644a4 Mon Sep 17 00:00:00 2001 From: gaba Date: Thu, 8 Jun 2017 10:47:17 -0700 Subject: [PATCH 01/19] Adding french translations. --- locales/fr.yml | 443 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 locales/fr.yml diff --git a/locales/fr.yml b/locales/fr.yml new file mode 100644 index 000000000..b9612fac5 --- /dev/null +++ b/locales/fr.yml @@ -0,0 +1,443 @@ +fr: + bandialog: + are_you_sure: "Êtes-vous sûr de vouloir bannir {0}?" + ban_user: "Bannir l'utilisateur ?" + banned_user: "Utilisateur banni" + cancel: Annuler + note: "Remarque: bannir cet utilisateur rejettera également ce commentaire." + yes_ban_user: "Oui, bannir cet utilisateur" + bio_offensive: "Cette biographie est offensante" + cancel: Annuler + characters_remaining: "caractères restants" + comment: + anon: Anonyme + ban_user: "Bannir utilisateur" + comment: "Publier un commentaire" + flagged: signalé + view_context: "Afficher le contexte" + comment_box: + post: "Publier" + cancel: "Annuler" + reply: "Répondre" + comment: "Publier un commentaire" + name: "Nom" + comment_post_notif: "Votre commentaire a été publié." + comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe\ + \ de modération passera en revue votre commentaire sous peu." + comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui\ + \ ne sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une\ + \ erreur, contactez notre équipe de modération." + characters_remaining: "caractères restants" + comment_is_best: "Ce commentaire est l'un des meilleurs" + comment_offensive: "Ce commentaire est offensant" + comment_plural: Commentaires + comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui ne\ + \ sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une erreur,\ + \ contactez notre équipe de modération." + comment_post_notif: "Votre commentaire a été publié." + comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe de\ + \ modération passera en revue votre commentaire sous peu." + community: + account_creation_date: "Date de création du compte" + active: Actif + admin: Administrateur + ads_marketing: "Cela ressemble à du marketing / un message publicitaire" + are_you_sure: "Êtes-vous sûr de vouloir bannir {0} ?" + ban_user: "Bannir l'utilisateur ?" + banned: Banni + banned_user: "Utilisateur banni" + cancel: Signalé + dont_like_username: "Je n'aime pas ce nom d'utilisateur" + flaggedaccounts: "Noms d'utilisateurs signalés" + flags: Signalements + impersonating: "Cet utilisateur se fait passer pour quelqu'un d'autre" + loading: "Chargement des résultats" + moderator: Modérateur + newsroom_role: "Rôle de la salle de presse" + no_flagged_accounts: "La liste des comptes signalés est vide." + no_results: "Aucun utilisateur n'a été trouvé avec ce nom d'utilisateur ou cette\ + \ adresse de messagerie. Ils se cachent !" + note: "Remarque: bannir cet utilisateur ne lui permettra pas de modifier les commentaires\ + \ ou de supprimer quoi que ce soit." + offensive: "Ce commentaire est offensant" + other: Autre + people: Gens + role: "Sélectionnez le rôle ..." + select_status: "Sélectionnez l'état ..." + spam_ads: "Spam / Annonces" + staff: "Équipe" + status: Statut + username_and_email: "Nom d'utilisateur et e-mail" + yes_ban_user: "Oui bannir l'utilisateur" + configure: + apply: Appliquer + banned_word_text: "Les commentaires qui contiennent ces mots ou ces expressions\ + \ (non sensibles à la casse) seront automatiquement supprimés du flux de commentaires.\ + \ Tapez un mot et appuyez sur Entrée ou Tabulation pour ajouter. En option,\ + \ envoyez une liste séparée par des virgules." + banned_words_title: "Liste des mots interdits" + close: "Fermer" + close_after: "Fermer les commentaires après" + close_stream: "Fermer le fil" + close_stream_configuration: "Ce fil de commentaires est actuellement fermé. En\ + \ ouvrant ce fil commentaire, de nouveaux commentaires peuvent être soumis et\ + \ publiés." + closed_comments_desc: "Écrivez un message à afficher lorsque votre fil de commentaires\ + \ est fermé et n'accepte plus de nouveaux commentaires." + closed_comments_label: "Écrire un message..." + closed_stream_settings: "Message de fil de commentaires fermé" + comment_count_error: "S'il vous plait, entrez un nombre valide." + comment_count_header: "Limiter la longueur d'un commentaire" + comment_count_text_post: caractères + comment_count_text_pre: "Les commentaires seront limités à" + comment_settings: Paramètres + comment_stream: "Fil de commentaires" + comment_stream_will_close: "Le fil de commentaires va se fermer dans" + community: Communauté + configure: Configurer + copy_and_paste: "Copiez et collez le code ci-dessous dans votre CMS pour inté\ + grer votre boîte de commentaires dans vos articles." + custom_css_url: "URL CSS personnalisée" + custom_css_url_desc: "URL d'une feuille de style CSS qui remplacera les styles\ + \ par défaut d'intégration des commentaires. Peut être interne ou externe." + dashboard: Tableau de bord + days: Journées + description: "En tant qu'administrateur, vous pouvez personnaliser les paramè\ + tres du fil de commentaires pour cet élément." + domain_list_text: "Entrez les domaines que vous souhaitez autoriser pour Talk,\ + \ par exemple vos environnements locaux de production et de production (ex :\ + \ localhost: 3000 staging.domain.com domain.com)." + domain_list_title: "Domaines autorisés" + edit_comment_timeframe_heading: "Modifier l'horodatage des commentaires" + edit_comment_timeframe_text_pre: "Les commentateurs auront" + edit_comment_timeframe_text_post: "secondes pour modifier leurs commentaires." + embed_comment_stream: "Intégrer le fil" + enable_premod_links_text: "Les modérateurs doivent approuver tout commentaire\ + \ contenant un lien avant sa publication." + enable_pre_moderation: "Activer modération a priori" + enable_pre_moderation_text: "Les modérateurs doivent approuver tout commentaire\ + \ avant qu'il ne soit publié." + enable_premod_links: "Modérer les commentaires contenant des liens" + enable_premod: "Activer la modération a priori" + enable_premod_description: "Les modérateurs doivent approuver tout commentaire\ + \ avant sa publication." + enable_premod_links_description: "Les modérateurs doivent approuver tout commentaire\ + \ contenant un lien avant sa publication." + enable_questionbox: "Posez une question aux lecteurs." + enable_questionbox_description: "Cette question apparaîtra en haut de ce fil de\ + \ commentaires. Demandez aux lecteurs de s'exprimer sur un sujet évoqué dans\ + \ l'article ou posez les termes de la discussion, etc." + hours: Heures + include_comment_stream: "Inclure la description du fil de commentaires pour les\ + \ lecteurs" + include_comment_stream_desc: "Écrivez un message à ajouter au haut de votre flux\ + \ de commentaires. Publiez un sujet de discussion, avec des suggestion sur la\ + \ tenue des débats, etc." + include_text: "Entrez votre texte ici." + include_question_here: "Écrivez votre question ici." + moderate: Modérer + moderation_settings: "Paramètres de la modération" + open: "Ouvert" + open_stream: "Ouvrir le fil" + open_stream_configuration: "Ce fil de commentaires est actuellement ouvert. En\ + \ fermant ce fil de commentaires, aucun nouveau commentaire ne pourra être envoyé\ + , les commentaires précédents seront toujours affichés." + require_email_verification: "Exiger une vérification de l'e-mail" + require_email_verification_text: "Les nouveaux utilisateurs doivent vérifier leur\ + \ adresse e-mail avant de commenter." + save_changes: "Sauvegarder les changements" + shortcuts: Raccourcis + sign_out: "Se Déconnecter" + stories: Histoires + stream_settings: "Paramètres du fil" + suspect_word_title: "Liste des mots suspects" + suspect_word_text: "Les commentaires contenant ces mots ou expressions (non sensibles\ + \ à la casse) seront mis en évidence dans le flux de commentaires. Tapez un\ + \ mot et appuyez sur Entrée ou Tabulation pour ajouter. En option, entrez une\ + \ liste séparée par des virgules." + tech_settings: "Paramètres techniques" + title: "Configurer le fil de commentaires" + weeks: Semaines + wordlist: "Mots interdits" + continue: Continuer + dashboard: + auto_update: "Les données sont automatiquement mises à jour toutes les cinq minutes\ + \ ou lorsque vous rechargez." + comment_count: commentaires + flags: signalements + most_flags: "Articles avec le plus de signalements" + most_conversations: "Articles avec le plus de conversations" + next_update: "{0} minutes jusqu'à la prochaine mise à jour." + no_activity: "Il n'y a eu aucun commentaire nulle part dans les cinq dernières\ + \ minutes." + no_flags: "Il n'y a pas eu aucun signalement au cours des 5 dernières minutes\ + \ ! Hooray !" + no_likes: "Il n'y a pas eu de \"J'aime\" au cours des 5 dernières minutes. Tout\ + \ est calme." + done: Terminé + edit_comment: + body_input_label: "Modifier ce commentaire" + save_button: "Sauvegarder les changements" + edit_window_expired: "Vous ne pouvez plus modifier ce commentaire. La fenêtre\ + \ de temps pour le faire a expiré. Pourquoi ne pas en publier un autre ?" + edit_window_expired_close: "Fermer" + edit_window_timer_prefix: "Fenêtre d'édition :" + second: "seconde" + seconds_plural: "secondes" + unexpected_error: "Erreur inattendue lors de l'enregistrement des modifications.\ + \ Désolé !" + embedlink: + copy: "Copier dans le presse-papier" + error: + COMMENT_TOO_SHORT: "Votre commentaire doit contenir quelque chose" + NOT_AUTHORIZED: "Vous n'êtes pas autorisé à effectuer cette action." + NO_SPECIAL_CHARACTERS: "Les noms d'utilisateur ne peuvent contenir que des lettres,\ + \ des chiffres et \"_\" seulement" + PASSWORD_LENGTH: "Le mot de passe est trop court" + PROFANITY_ERROR: "Les noms d'utilisateur ne doivent pas contenir de mots offensants.\ + \ Veuillez contacter l'administrateur si vous pensez qu'il y a une erreur." + USERNAME_IN_USE: "Ce nom d'utilisateur est déjà pris" + USERNAME_REQUIRED: "Doit entrer un nom d'utilisateur" + EDIT_WINDOW_ENDED: "Vous ne pouvez plus modifier ce commentaire. La fenêtre de\ + \ temps pour le faire a expiré." + EDIT_USERNAME_NOT_AUTHORIZED: "Vous n'avez pas la permission de mettre à jour\ + \ votre nom d'utilisateur." + EMAIL_IN_USE: "Adresse e-mail déjà utilisée" + EMAIL_REQUIRED: "Une adresse email est requise" + LOGIN_MAXIMUM_EXCEEDED: "Vous avez effectué trop de tentatives infructueuses pour\ + \ entrer votre mot de passe. S'il vous plaît, attendez." + PASSWORD_REQUIRED: "Doit entrer un mot de passe" + COMMENTING_CLOSED: "Les commentaires sont déjà fermés" + NOT_FOUND: "Ressource introuvable" + INVALID_ASSET_URL: "L'URL est invalide" + email: "Pas une adresse e-mail valide" + confirm_password: "Les mots de passe ne correspondent pas. Vérifiez à nouveau" + network_error: "Échec de connexion au serveur. Vérifiez votre connexion Internet\ + \ et réessayez." + email_not_verified: "L'adresse e-mail {0} n'est pas vérifiée." + email_password: "Combinaison e-mail / mot de passe incorrecte." + organization_name: "Le nom de l'organisation ne peut contenir que des lettres\ + \ ou des chiffres." + password: "Le mot de passe doit être d'au moins 8 caractères" + username: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres\ + \ et \"_\"" + flag_comment: "Signaler un commentaire" + flag_reason: "Motif du signalement (facultatif)" + flag_username: "Signaler un nom d'utilisateur" + framework: + banned_account_msg: "Votre compte est actuellement suspendu. Cela signifie que\ + \ vous ne pouvez pas Aimer Signaler ou Écrire des commentaires. Contactez-nous\ + \ si vous avez des questions." + comment: commentaire + comment_is_ignored: "Ce commentaire est caché car vous avez ignoré cet utilisateur." + comments: commentaires + configure_stream: "Configure le fil" + content_not_available: "Ce contenu n'est pas disponible" + edit_name: + button: Soumettre + error: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres\ + \ et \"_\"" + label: "Nouveau nom d'utilisateur" + msg: "Votre compte est actuellement suspendu car votre nom d'utilisateur a é\ + té jugé inapproprié. Pour restaurer votre compte, entrez un nouveau nom d'utilisateur.\ + \ Contactez-nous si vous avez des questions." + ignored_users: "Utilisateurs ignorés" + my_comments: "Mes commentaires" + my_profile: "Mon profil" + new_count: "Voir {0} nouveau {1}" + profile: Profil + show_all_comments: "Afficher tous les commentaires" + success_bio_update: "Votre biographie a été mise à jour" + success_name_update: "Votre nom d'utilisateur a été mis à jour" + success_update_settings: "Les modifications que vous avez apportées ont été appliqué\ + es au fil de commentaires sur cet article" + view_all_replies: "Voir {0} réponses" + view_all_replies_initial: "Voir toutes les {0} réponses" + view_more_comments: "Voir plus de commentaires" + view_reply: "Voir la réponse" + from_settings_page: "Dans la page Profil, vous pouvez voir l'historique de vos commentaires." + like: "J'aime" + loading_results: "Chargement des résultats" + marketing: "Cela ressemble à du marketing / une publicité" + moderate_this_stream: "Modifiez ce fil" + modqueue: + account: "Signalements du compte" + actions: Actions + all: tous + all_streams: "Tous les fils" + approve: "Approuver" + approved: "Approuvé" + ban_user: "Bannir" + billion: B + close: Fermer + dont_like_username: "N'aime pas le nom d'utilisateur" + empty_queue: "Plus de commentaires à modérer ! Vous avez terminé, allez prendre\ + \ un ☕️" + flagged: signalé + impersonating: "problème d'identité" + less_detail: "Moins de détails" + likes: "J'aime" + million: M + mod_faster: "Modérer plus rapidement avec les raccourcis clavier" + moderate: "Modérer →" + more_detail: "Plus de détails" + newest_first: "Le plus récent d'abord" + navigation: Navigation + next_comment: "Aller au prochain commentaire" + offensive: Offensant + oldest_first: "Le plus ancien d'abord" + other: Autre + premod: Pre-modérer + prev_comment: "Aller au commentaire précédent" + reject: "Rejeter" + rejected: "Rejeté" + select_stream: "Sélectionnez le fil" + shift_key: ⇧ + shortcuts: Raccourcis + show_shortcuts: "Afficher les raccourcis" + singleview: "Passer en mode d'édition de commentaire unique" + spam_ads: Spam / Publicités + thismenu: "Ouvrir ce menu" + thousand: k + try_these: "Essayez ces" + view_more_shortcuts: "Afficher plus de raccourcis" + my_comment_history: "Mon historique de commentaires" + name: Nom + no_agree_comment: "Je ne suis pas d'accord avec ce commentaire" + no_like_bio: "Je n'aime pas cette biographie" + no_like_username: "Je n'aime pas ce nom d'utilisateur" + other: Autre + permalink: Lien + personal_info: "Ce commentaire révèle des informations personnelles identifiables" + post: Publier + profile: Profil + profile_settings: "Paramètres du profil" + reply: Répondre + report: Signaler + report_notif: "Merci de signaler ce commentaire. Notre équipe de modération a é\ + té informée." + report_notif_remove: "Votre signalement a été supprimé." + reported: Signalé + set_best: "Sélectionner comme le meilleur" + settings: + all_comments: "Tous les commentaires" + from_settings_page: "Dans la page Profil, vous pouvez voir l'historique de vos\ + \ commentaires." + my_comment_history: "Mon historique de commentaires" + profile: Profil + profile_settings: "Paramètres du profil" + sign_in: "Se connecter" + to_access: "Accéder au profil" + user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation\ + \ !" + stream: + temporarily_suspended: "Conformément à la charte d'utilisation des commentaires\ + \ de {0}, votre compte a été temporairement suspendu. Merci de revenir dans\ + \ la conversation {1}." + step_1_header: "Signaler un problème" + step_2_header: "Aidez-nous à comprendre" + step_3_header: "Merci pour votre participation" + streams: + all: Tous + article: Récit + closed: Fermé + empty_result: "Aucun contenu ne correspond à cette recherche. Peut-être essayer\ + \ d'élargir votre recherche ?" + filter_streams: "Filtrer les flux" + newest: Le plus récent + oldest: Le plus ancien + open: Ouvrir + pubdate: "Date de publication" + search: Recherche + sort_by: "Trier par" + status: "Statut du fil" + stream_status: "Statut du fil" + suspenduser: + bio: Bio + cancel: "Annuler" + days: "{0} jours" + description_0: "Voulez-vous interdire temporairement cet utilisateur en raison\ + \ de leur {0} ? Cela dissimulera temporairement leurs commentaires jusqu'à ce\ + \ qu'ils réécrivent leurs {0}." + description_1: "Suspendre cet utilisateur désactivera temporairement son compte\ + \ et cachera tous ses commentaires sur le site." + description_notify: "Suspendre cet utilisateur désactivera temporairement son\ + \ compte et cachera tous ses commentaires sur le site." + description_reject: "Voulez-vous interdire temporairement cet utilisateur en raison\ + \ de leur {0}? Cela dissimulera temporairement leurs commentaires jusqu'à ce\ + \ qu'ils réécrivent leurs {0}." + description_suspend: "Vous suspendez {0}. Ce commentaire sera rejeté, et {0} ne\ + \ sera pas autorisé à aimer, à signaler, à répondre ou à publier jusqu'à ce\ + \ que la suspension soit levée." + email: "Un autre membre de la communauté a récemment signalé votre nom d'utilisateur\ + \ pour examen. En raison de son contenu, votre utilisateur a été rejeté. Cela\ + \ signifie que vous ne pouvez plus commenter ou signaler du contenu jusqu'à\ + \ ce que vous changiez votre nom d'utilisateur. Veuillez nous envoyer un e-mail\ + \ si vous avez des questions ou des préoccupations." + email_subject: "Votre compte a été suspendu" + email_message_reject: "Un autre membre de la communauté a récemment signalé votre\ + \ nom d'utilisateur pour examen. En raison de son contenu, votre nom d'utilisateur\ + \ a été rejeté. Cela signifie que vous ne pouvez plus commenter, ni signaler\ + \ du contenu jusqu'à ce que vous changiez votre nom d'utilisateur. Veuillez\ + \ nous envoyer un e-mail si vous avez des questions ou des préoccupations." + email_message_suspend: "Cher {0},\n\nConformément à la charte des commentaires\ + \ de {1}, votre compte a été temporairement suspendu. Pendant cette période,\ + \ vous ne pourrez pas commenter, signaler ou participer à d'autres commentaires.\ + \ \n\nMerci de revenir dans la conversation {2}." + error_email_message_empty: "Vous devez spécifier un message dans l'e-mail." + hours: "{0} heures" + no_cancel: "Pas d'annulation" + notify_suspend_until: "L'utilisateur {0} a été temporairement suspendu. Cette\ + \ suspension se terminera automatiquement {1}." + one_hour: "1 heure" + send: Envoyer + select_duration: "Sélectionnez la durée de la suspension" + suspend_user: "Suspendre l'utilisateur" + title: "Suspendre un utilisateur" + title_0: "Nous avons remarqué que vous avez rejeté un nom d'utilisateur" + title_1: "Aviser l'utilisateur de sa suspension temporaire" + title_notify: "Aviser l'utilisateur de sa suspension temporaire" + title_reject: "Nous avons remarqué que vous avez rejeté un nom d'utilisateur" + title_suspend: "Suspendre l'utilisateur" + username: "Nom d'utilisateur" + write_message: "Écrire un message" + yes_suspend: "Oui suspendre" + thank_you: "Nous apprécions vos commentaires. Un modérateur passera en revue votre\ + \ signalement. Merci pour votre aide." + unset_best: "Déselectionner comme le meilleur" + user: + bio_flags: "Signaler pour cette biographie" + user_bio: "Bio de l'utilisateur" + username_flags: "Signaler pour ce nom d'utilisateur" + user_impersonating: "Cet utilisateur se fait passer pour quelqu'un d'autre" + user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation\ + \ !" + username_offensive: "Ce nom d'utilisateur est offensant" + view_conversation: "Afficher la conversation" + install: + initial: + description: "Configurez votre communauté Talk en quelques petites étapes." + submit: "Commencer" + add_organization: + description: "Veuillez nous indiquer le nom de votre organisation. Cela apparaî\ + tra dans les e-mails lors de l'invitation de nouveaux membres dans l'équipe." + label: "Nom de l'organisation" + save: "Sauvegarder" + create: + email: "Adresse e-mail" + username: "Nom d'utilisateur" + password: "Mot de passe" + confirm_password: "Confirmez Le mot de passe" + save: "Sauvegarder" + permitted_domains: + title: "Domaines autorisés" + description: "Entrez les domaines que vous souhaitez autoriser pour Talk, par\ + \ ex. vos environnements locaux, de déploiement et de production (ex localhost:\ + \ 3000, staging.domain.com, domain.com)." + submit: "Terminer l'installation" + final: + description: "Merci d'avoir installé Talk ! Nous avons envoyé un e-mail pour\ + \ vérifier votre adresse électronique. Pendant que vous terminez la configuration,\ + \ vous pouvez commencer à engager vos lecteurs dès maintenant." + launch: "Lancer Talk" + close: "Fermez cet installateur" From 19b6dfaa0a7a88857eeca0250583b82e12ec5dbc Mon Sep 17 00:00:00 2001 From: gaba Date: Thu, 8 Jun 2017 11:39:51 -0700 Subject: [PATCH 02/19] Adding a new language is not so straight forward. It needs to change at some point. --- client/coral-framework/services/i18n.js | 5 +- locales/fr.yml | 210 +++++++----------------- services/i18n.js | 6 +- 3 files changed, 69 insertions(+), 152 deletions(-) diff --git a/client/coral-framework/services/i18n.js b/client/coral-framework/services/i18n.js index c78c460e0..8202b599b 100644 --- a/client/coral-framework/services/i18n.js +++ b/client/coral-framework/services/i18n.js @@ -4,13 +4,15 @@ import get from 'lodash/get'; import merge from 'lodash/merge'; import esTA from '../../../node_modules/timeago.js/locales/es'; +import frTA from '../../../node_modules/timeago.js/locales/fr'; import en from '../../../locales/en.yml'; import es from '../../../locales/es.yml'; +import fr from '../../../locales/fr.yml'; // Translations are happening at https://translate.lingohub.com/the-coral-project/dashboard const defaultLanguage = 'en'; -const translations = {...en, ...es}; +const translations = {...en, ...es, ...fr}; let lang; let timeagoInstance; @@ -40,6 +42,7 @@ function init() { } ta.register('es', esTA); + ta.register('fr', frTA); timeagoInstance = ta(); } diff --git a/locales/fr.yml b/locales/fr.yml index b9612fac5..77231e17b 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -22,21 +22,15 @@ fr: comment: "Publier un commentaire" name: "Nom" comment_post_notif: "Votre commentaire a été publié." - comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe\ - \ de modération passera en revue votre commentaire sous peu." - comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui\ - \ ne sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une\ - \ erreur, contactez notre équipe de modération." + comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe de modération passera en revue votre commentaire sous peu." + comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui ne sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une erreur, contactez notre équipe de modération." characters_remaining: "caractères restants" comment_is_best: "Ce commentaire est l'un des meilleurs" comment_offensive: "Ce commentaire est offensant" comment_plural: Commentaires - comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui ne\ - \ sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une erreur,\ - \ contactez notre équipe de modération." + comment_post_banned_word: "Votre commentaire contient un ou plusieurs mots qui ne sont pas autorisés, il ne sera pas publié. Si vous pensez qu'il y a une erreur, contactez notre équipe de modération." comment_post_notif: "Votre commentaire a été publié." - comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe de\ - \ modération passera en revue votre commentaire sous peu." + comment_post_notif_premod: "Merci d'avoir envoyé un commentaire. Notre équipe de modération passera en revue votre commentaire sous peu." community: account_creation_date: "Date de création du compte" active: Actif @@ -55,10 +49,8 @@ fr: moderator: Modérateur newsroom_role: "Rôle de la salle de presse" no_flagged_accounts: "La liste des comptes signalés est vide." - no_results: "Aucun utilisateur n'a été trouvé avec ce nom d'utilisateur ou cette\ - \ adresse de messagerie. Ils se cachent !" - note: "Remarque: bannir cet utilisateur ne lui permettra pas de modifier les commentaires\ - \ ou de supprimer quoi que ce soit." + no_results: "Aucun utilisateur n'a été trouvé avec ce nom d'utilisateur ou cette adresse de messagerie. Ils se cachent !" + note: "Remarque: bannir cet utilisateur ne lui permettra pas de modifier les commentaires ou de supprimer quoi que ce soit." offensive: "Ce commentaire est offensant" other: Autre people: Gens @@ -71,19 +63,13 @@ fr: yes_ban_user: "Oui bannir l'utilisateur" configure: apply: Appliquer - banned_word_text: "Les commentaires qui contiennent ces mots ou ces expressions\ - \ (non sensibles à la casse) seront automatiquement supprimés du flux de commentaires.\ - \ Tapez un mot et appuyez sur Entrée ou Tabulation pour ajouter. En option,\ - \ envoyez une liste séparée par des virgules." + banned_word_text: "Les commentaires qui contiennent ces mots ou ces expressions (non sensibles à la casse) seront automatiquement supprimés du flux de commentaires. Tapez un mot et appuyez sur Entrée ou Tabulation pour ajouter. En option, envoyez une liste séparée par des virgules." banned_words_title: "Liste des mots interdits" close: "Fermer" close_after: "Fermer les commentaires après" close_stream: "Fermer le fil" - close_stream_configuration: "Ce fil de commentaires est actuellement fermé. En\ - \ ouvrant ce fil commentaire, de nouveaux commentaires peuvent être soumis et\ - \ publiés." - closed_comments_desc: "Écrivez un message à afficher lorsque votre fil de commentaires\ - \ est fermé et n'accepte plus de nouveaux commentaires." + close_stream_configuration: "Ce fil de commentaires est actuellement fermé. En ouvrant ce fil commentaire, de nouveaux commentaires peuvent être soumis et publiés." + closed_comments_desc: "Écrivez un message à afficher lorsque votre fil de commentaires est fermé et n'accepte plus de nouveaux commentaires." closed_comments_label: "Écrire un message..." closed_stream_settings: "Message de fil de commentaires fermé" comment_count_error: "S'il vous plait, entrez un nombre valide." @@ -95,139 +81,103 @@ fr: comment_stream_will_close: "Le fil de commentaires va se fermer dans" community: Communauté configure: Configurer - copy_and_paste: "Copiez et collez le code ci-dessous dans votre CMS pour inté\ - grer votre boîte de commentaires dans vos articles." + copy_and_paste: "Copiez et collez le code ci-dessous dans votre CMS pour intégrer votre boîte de commentaires dans vos articles." custom_css_url: "URL CSS personnalisée" - custom_css_url_desc: "URL d'une feuille de style CSS qui remplacera les styles\ - \ par défaut d'intégration des commentaires. Peut être interne ou externe." + custom_css_url_desc: "URL d'une feuille de style CSS qui remplacera les styles par défaut d'intégration des commentaires. Peut être interne ou externe." dashboard: Tableau de bord days: Journées - description: "En tant qu'administrateur, vous pouvez personnaliser les paramè\ - tres du fil de commentaires pour cet élément." - domain_list_text: "Entrez les domaines que vous souhaitez autoriser pour Talk,\ - \ par exemple vos environnements locaux de production et de production (ex :\ - \ localhost: 3000 staging.domain.com domain.com)." + description: "En tant qu'administrateur, vous pouvez personnaliser les paramètres du fil de commentaires pour cet élément." + domain_list_text: "Entrez les domaines que vous souhaitez autoriser pour Talk, par exemple vos environnements locaux de production et de production (ex : localhost: 3000 staging.domain.com domain.com)." domain_list_title: "Domaines autorisés" edit_comment_timeframe_heading: "Modifier l'horodatage des commentaires" edit_comment_timeframe_text_pre: "Les commentateurs auront" edit_comment_timeframe_text_post: "secondes pour modifier leurs commentaires." embed_comment_stream: "Intégrer le fil" - enable_premod_links_text: "Les modérateurs doivent approuver tout commentaire\ - \ contenant un lien avant sa publication." + enable_premod_links_text: "Les modérateurs doivent approuver tout commentaire contenant un lien avant sa publication." enable_pre_moderation: "Activer modération a priori" - enable_pre_moderation_text: "Les modérateurs doivent approuver tout commentaire\ - \ avant qu'il ne soit publié." + enable_pre_moderation_text: "Les modérateurs doivent approuver tout commentaire avant qu'il ne soit publié." enable_premod_links: "Modérer les commentaires contenant des liens" enable_premod: "Activer la modération a priori" - enable_premod_description: "Les modérateurs doivent approuver tout commentaire\ - \ avant sa publication." - enable_premod_links_description: "Les modérateurs doivent approuver tout commentaire\ - \ contenant un lien avant sa publication." + enable_premod_description: "Les modérateurs doivent approuver tout commentaire avant sa publication." + enable_premod_links_description: "Les modérateurs doivent approuver tout commentaire contenant un lien avant sa publication." enable_questionbox: "Posez une question aux lecteurs." - enable_questionbox_description: "Cette question apparaîtra en haut de ce fil de\ - \ commentaires. Demandez aux lecteurs de s'exprimer sur un sujet évoqué dans\ - \ l'article ou posez les termes de la discussion, etc." + enable_questionbox_description: "Cette question apparaîtra en haut de ce fil de commentaires. Demandez aux lecteurs de s'exprimer sur un sujet évoqué dans l'article ou posez les termes de la discussion, etc." hours: Heures - include_comment_stream: "Inclure la description du fil de commentaires pour les\ - \ lecteurs" - include_comment_stream_desc: "Écrivez un message à ajouter au haut de votre flux\ - \ de commentaires. Publiez un sujet de discussion, avec des suggestion sur la\ - \ tenue des débats, etc." + include_comment_stream: "Inclure la description du fil de commentaires pour les lecteurs" + include_comment_stream_desc: "Écrivez un message à ajouter au haut de votre flux de commentaires. Publiez un sujet de discussion, avec des suggestion sur la tenue des débats, etc." include_text: "Entrez votre texte ici." include_question_here: "Écrivez votre question ici." moderate: Modérer moderation_settings: "Paramètres de la modération" open: "Ouvert" open_stream: "Ouvrir le fil" - open_stream_configuration: "Ce fil de commentaires est actuellement ouvert. En\ - \ fermant ce fil de commentaires, aucun nouveau commentaire ne pourra être envoyé\ - , les commentaires précédents seront toujours affichés." + open_stream_configuration: "Ce fil de commentaires est actuellement ouvert. En fermant ce fil de commentaires, aucun nouveau commentaire ne pourra être envoyé, les commentaires précédents seront toujours affichés." require_email_verification: "Exiger une vérification de l'e-mail" - require_email_verification_text: "Les nouveaux utilisateurs doivent vérifier leur\ - \ adresse e-mail avant de commenter." + require_email_verification_text: "Les nouveaux utilisateurs doivent vérifier leur adresse e-mail avant de commenter." save_changes: "Sauvegarder les changements" shortcuts: Raccourcis sign_out: "Se Déconnecter" stories: Histoires stream_settings: "Paramètres du fil" suspect_word_title: "Liste des mots suspects" - suspect_word_text: "Les commentaires contenant ces mots ou expressions (non sensibles\ - \ à la casse) seront mis en évidence dans le flux de commentaires. Tapez un\ - \ mot et appuyez sur Entrée ou Tabulation pour ajouter. En option, entrez une\ - \ liste séparée par des virgules." + suspect_word_text: "Les commentaires contenant ces mots ou expressions (non sensibles à la casse) seront mis en évidence dans le flux de commentaires. Tapez un mot et appuyez sur Entrée ou Tabulation pour ajouter. En option, entrez une liste séparée par des virgules." tech_settings: "Paramètres techniques" title: "Configurer le fil de commentaires" weeks: Semaines wordlist: "Mots interdits" continue: Continuer dashboard: - auto_update: "Les données sont automatiquement mises à jour toutes les cinq minutes\ - \ ou lorsque vous rechargez." + auto_update: "Les données sont automatiquement mises à jour toutes les cinq minutes ou lorsque vous rechargez." comment_count: commentaires flags: signalements most_flags: "Articles avec le plus de signalements" most_conversations: "Articles avec le plus de conversations" next_update: "{0} minutes jusqu'à la prochaine mise à jour." - no_activity: "Il n'y a eu aucun commentaire nulle part dans les cinq dernières\ - \ minutes." - no_flags: "Il n'y a pas eu aucun signalement au cours des 5 dernières minutes\ - \ ! Hooray !" - no_likes: "Il n'y a pas eu de \"J'aime\" au cours des 5 dernières minutes. Tout\ - \ est calme." + no_activity: "Il n'y a eu aucun commentaire nulle part dans les cinq dernières minutes." + no_flags: "Il n'y a pas eu aucun signalement au cours des 5 dernières minutes! Hooray !" + no_likes: "Il n'y a pas eu de \"J'aime\" au cours des 5 dernières minutes. Tout est calme." done: Terminé edit_comment: body_input_label: "Modifier ce commentaire" save_button: "Sauvegarder les changements" - edit_window_expired: "Vous ne pouvez plus modifier ce commentaire. La fenêtre\ - \ de temps pour le faire a expiré. Pourquoi ne pas en publier un autre ?" + edit_window_expired: "Vous ne pouvez plus modifier ce commentaire. La fenêtre de temps pour le faire a expiré. Pourquoi ne pas en publier un autre ?" edit_window_expired_close: "Fermer" edit_window_timer_prefix: "Fenêtre d'édition :" second: "seconde" seconds_plural: "secondes" - unexpected_error: "Erreur inattendue lors de l'enregistrement des modifications.\ - \ Désolé !" + unexpected_error: "Erreur inattendue lors de l'enregistrement des modifications. Désolé !" embedlink: copy: "Copier dans le presse-papier" error: COMMENT_TOO_SHORT: "Votre commentaire doit contenir quelque chose" NOT_AUTHORIZED: "Vous n'êtes pas autorisé à effectuer cette action." - NO_SPECIAL_CHARACTERS: "Les noms d'utilisateur ne peuvent contenir que des lettres,\ - \ des chiffres et \"_\" seulement" + NO_SPECIAL_CHARACTERS: "Les noms d'utilisateur ne peuvent contenir que des lettres, des chiffres et \"_\" seulement" PASSWORD_LENGTH: "Le mot de passe est trop court" - PROFANITY_ERROR: "Les noms d'utilisateur ne doivent pas contenir de mots offensants.\ - \ Veuillez contacter l'administrateur si vous pensez qu'il y a une erreur." + PROFANITY_ERROR: "Les noms d'utilisateur ne doivent pas contenir de mots offensants. Veuillez contacter l'administrateur si vous pensez qu'il y a une erreur." USERNAME_IN_USE: "Ce nom d'utilisateur est déjà pris" USERNAME_REQUIRED: "Doit entrer un nom d'utilisateur" - EDIT_WINDOW_ENDED: "Vous ne pouvez plus modifier ce commentaire. La fenêtre de\ - \ temps pour le faire a expiré." - EDIT_USERNAME_NOT_AUTHORIZED: "Vous n'avez pas la permission de mettre à jour\ - \ votre nom d'utilisateur." + EDIT_WINDOW_ENDED: "Vous ne pouvez plus modifier ce commentaire. La fenêtre de temps pour le faire a expiré." + EDIT_USERNAME_NOT_AUTHORIZED: "Vous n'avez pas la permission de mettre à jour votre nom d'utilisateur." EMAIL_IN_USE: "Adresse e-mail déjà utilisée" EMAIL_REQUIRED: "Une adresse email est requise" - LOGIN_MAXIMUM_EXCEEDED: "Vous avez effectué trop de tentatives infructueuses pour\ - \ entrer votre mot de passe. S'il vous plaît, attendez." + LOGIN_MAXIMUM_EXCEEDED: "Vous avez effectué trop de tentatives infructueuses pour entrer votre mot de passe. S'il vous plaît, attendez." PASSWORD_REQUIRED: "Doit entrer un mot de passe" COMMENTING_CLOSED: "Les commentaires sont déjà fermés" NOT_FOUND: "Ressource introuvable" INVALID_ASSET_URL: "L'URL est invalide" email: "Pas une adresse e-mail valide" confirm_password: "Les mots de passe ne correspondent pas. Vérifiez à nouveau" - network_error: "Échec de connexion au serveur. Vérifiez votre connexion Internet\ - \ et réessayez." + network_error: "Échec de connexion au serveur. Vérifiez votre connexion Internet et réessayez." email_not_verified: "L'adresse e-mail {0} n'est pas vérifiée." email_password: "Combinaison e-mail / mot de passe incorrecte." - organization_name: "Le nom de l'organisation ne peut contenir que des lettres\ - \ ou des chiffres." + organization_name: "Le nom de l'organisation ne peut contenir que des lettres ou des chiffres." password: "Le mot de passe doit être d'au moins 8 caractères" - username: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres\ - \ et \"_\"" + username: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres et \"_\"" flag_comment: "Signaler un commentaire" flag_reason: "Motif du signalement (facultatif)" flag_username: "Signaler un nom d'utilisateur" framework: - banned_account_msg: "Votre compte est actuellement suspendu. Cela signifie que\ - \ vous ne pouvez pas Aimer Signaler ou Écrire des commentaires. Contactez-nous\ - \ si vous avez des questions." + banned_account_msg: "Votre compte est actuellement suspendu. Cela signifie que vous ne pouvez pas Aimer Signaler ou Écrire des commentaires. Contactez-nous si vous avez des questions." comment: commentaire comment_is_ignored: "Ce commentaire est caché car vous avez ignoré cet utilisateur." comments: commentaires @@ -235,12 +185,9 @@ fr: content_not_available: "Ce contenu n'est pas disponible" edit_name: button: Soumettre - error: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres\ - \ et \"_\"" + error: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres et \"_\"" label: "Nouveau nom d'utilisateur" - msg: "Votre compte est actuellement suspendu car votre nom d'utilisateur a é\ - té jugé inapproprié. Pour restaurer votre compte, entrez un nouveau nom d'utilisateur.\ - \ Contactez-nous si vous avez des questions." + msg: "Votre compte est actuellement suspendu car votre nom d'utilisateur a été jugé inapproprié. Pour restaurer votre compte, entrez un nouveau nom d'utilisateur. Contactez-nous si vous avez des questions." ignored_users: "Utilisateurs ignorés" my_comments: "Mes commentaires" my_profile: "Mon profil" @@ -249,8 +196,7 @@ fr: show_all_comments: "Afficher tous les commentaires" success_bio_update: "Votre biographie a été mise à jour" success_name_update: "Votre nom d'utilisateur a été mis à jour" - success_update_settings: "Les modifications que vous avez apportées ont été appliqué\ - es au fil de commentaires sur cet article" + success_update_settings: "Les modifications que vous avez apportées ont été appliqué es au fil de commentaires sur cet article" view_all_replies: "Voir {0} réponses" view_all_replies_initial: "Voir toutes les {0} réponses" view_more_comments: "Voir plus de commentaires" @@ -271,8 +217,7 @@ fr: billion: B close: Fermer dont_like_username: "N'aime pas le nom d'utilisateur" - empty_queue: "Plus de commentaires à modérer ! Vous avez terminé, allez prendre\ - \ un ☕️" + empty_queue: "Plus de commentaires à modérer ! Vous avez terminé, allez prendre un ☕️" flagged: signalé impersonating: "problème d'identité" less_detail: "Moins de détails" @@ -314,26 +259,21 @@ fr: profile_settings: "Paramètres du profil" reply: Répondre report: Signaler - report_notif: "Merci de signaler ce commentaire. Notre équipe de modération a é\ - té informée." + report_notif: "Merci de signaler ce commentaire. Notre équipe de modération a é té informée." report_notif_remove: "Votre signalement a été supprimé." reported: Signalé set_best: "Sélectionner comme le meilleur" settings: all_comments: "Tous les commentaires" - from_settings_page: "Dans la page Profil, vous pouvez voir l'historique de vos\ - \ commentaires." + from_settings_page: "Dans la page Profil, vous pouvez voir l'historique de vos commentaires." my_comment_history: "Mon historique de commentaires" profile: Profil profile_settings: "Paramètres du profil" sign_in: "Se connecter" to_access: "Accéder au profil" - user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation\ - \ !" + user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation!" stream: - temporarily_suspended: "Conformément à la charte d'utilisation des commentaires\ - \ de {0}, votre compte a été temporairement suspendu. Merci de revenir dans\ - \ la conversation {1}." + temporarily_suspended: "Conformément à la charte d'utilisation des commentaires de {0}, votre compte a été temporairement suspendu. Merci de revenir dans la conversation {1}." step_1_header: "Signaler un problème" step_2_header: "Aidez-nous à comprendre" step_3_header: "Merci pour votre participation" @@ -341,8 +281,7 @@ fr: all: Tous article: Récit closed: Fermé - empty_result: "Aucun contenu ne correspond à cette recherche. Peut-être essayer\ - \ d'élargir votre recherche ?" + empty_result: "Aucun contenu ne correspond à cette recherche. Peut-être essayer d'élargir votre recherche ?" filter_streams: "Filtrer les flux" newest: Le plus récent oldest: Le plus ancien @@ -356,39 +295,19 @@ fr: bio: Bio cancel: "Annuler" days: "{0} jours" - description_0: "Voulez-vous interdire temporairement cet utilisateur en raison\ - \ de leur {0} ? Cela dissimulera temporairement leurs commentaires jusqu'à ce\ - \ qu'ils réécrivent leurs {0}." - description_1: "Suspendre cet utilisateur désactivera temporairement son compte\ - \ et cachera tous ses commentaires sur le site." - description_notify: "Suspendre cet utilisateur désactivera temporairement son\ - \ compte et cachera tous ses commentaires sur le site." - description_reject: "Voulez-vous interdire temporairement cet utilisateur en raison\ - \ de leur {0}? Cela dissimulera temporairement leurs commentaires jusqu'à ce\ - \ qu'ils réécrivent leurs {0}." - description_suspend: "Vous suspendez {0}. Ce commentaire sera rejeté, et {0} ne\ - \ sera pas autorisé à aimer, à signaler, à répondre ou à publier jusqu'à ce\ - \ que la suspension soit levée." - email: "Un autre membre de la communauté a récemment signalé votre nom d'utilisateur\ - \ pour examen. En raison de son contenu, votre utilisateur a été rejeté. Cela\ - \ signifie que vous ne pouvez plus commenter ou signaler du contenu jusqu'à\ - \ ce que vous changiez votre nom d'utilisateur. Veuillez nous envoyer un e-mail\ - \ si vous avez des questions ou des préoccupations." + description_0: "Voulez-vous interdire temporairement cet utilisateur en raison de leur {0} ? Cela dissimulera temporairement leurs commentaires jusqu'à ce qu'ils réécrivent leurs {0}." + description_1: "Suspendre cet utilisateur désactivera temporairement son compte et cachera tous ses commentaires sur le site." + description_notify: "Suspendre cet utilisateur désactivera temporairement son compte et cachera tous ses commentaires sur le site." + description_reject: "Voulez-vous interdire temporairement cet utilisateur en raison de leur {0}? Cela dissimulera temporairement leurs commentaires jusqu'à ce qu'ils réécrivent leurs {0}." + description_suspend: "Vous suspendez {0}. Ce commentaire sera rejeté, et {0} ne sera pas autorisé à aimer, à signaler, à répondre ou à publier jusqu'à ce que la suspension soit levée." + email: "Un autre membre de la communauté a récemment signalé votre nom d'utilisateur pour examen. En raison de son contenu, votre utilisateur a été rejeté. Cela signifie que vous ne pouvez plus commenter ou signaler du contenu jusqu'à ce que vous changiez votre nom d'utilisateur. Veuillez nous envoyer un e-mail si vous avez des questions ou des préoccupations." email_subject: "Votre compte a été suspendu" - email_message_reject: "Un autre membre de la communauté a récemment signalé votre\ - \ nom d'utilisateur pour examen. En raison de son contenu, votre nom d'utilisateur\ - \ a été rejeté. Cela signifie que vous ne pouvez plus commenter, ni signaler\ - \ du contenu jusqu'à ce que vous changiez votre nom d'utilisateur. Veuillez\ - \ nous envoyer un e-mail si vous avez des questions ou des préoccupations." - email_message_suspend: "Cher {0},\n\nConformément à la charte des commentaires\ - \ de {1}, votre compte a été temporairement suspendu. Pendant cette période,\ - \ vous ne pourrez pas commenter, signaler ou participer à d'autres commentaires.\ - \ \n\nMerci de revenir dans la conversation {2}." + email_message_reject: "Un autre membre de la communauté a récemment signalé votre nom d'utilisateur pour examen. En raison de son contenu, votre nom d'utilisateur a été rejeté. Cela signifie que vous ne pouvez plus commenter, ni signaler du contenu jusqu'à ce que vous changiez votre nom d'utilisateur. Veuillez nous envoyer un e-mail si vous avez des questions ou des préoccupations." + email_message_suspend: "Cher {0},\n\nConformément à la charte des commentaires de {1}, votre compte a été temporairement suspendu. Pendant cette période, vous ne pourrez pas commenter, signaler ou participer à d'autres commentaires. \n\nMerci de revenir dans la conversation {2}." error_email_message_empty: "Vous devez spécifier un message dans l'e-mail." hours: "{0} heures" no_cancel: "Pas d'annulation" - notify_suspend_until: "L'utilisateur {0} a été temporairement suspendu. Cette\ - \ suspension se terminera automatiquement {1}." + notify_suspend_until: "L'utilisateur {0} a été temporairement suspendu. Cette suspension se terminera automatiquement {1}." one_hour: "1 heure" send: Envoyer select_duration: "Sélectionnez la durée de la suspension" @@ -402,16 +321,14 @@ fr: username: "Nom d'utilisateur" write_message: "Écrire un message" yes_suspend: "Oui suspendre" - thank_you: "Nous apprécions vos commentaires. Un modérateur passera en revue votre\ - \ signalement. Merci pour votre aide." + thank_you: "Nous apprécions vos commentaires. Un modérateur passera en revue votre signalement. Merci pour votre aide." unset_best: "Déselectionner comme le meilleur" user: bio_flags: "Signaler pour cette biographie" user_bio: "Bio de l'utilisateur" username_flags: "Signaler pour ce nom d'utilisateur" user_impersonating: "Cet utilisateur se fait passer pour quelqu'un d'autre" - user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation\ - \ !" + user_no_comment: "Vous n'avez jamais laissé de commentaire. Rejoignez la conversation !" username_offensive: "Ce nom d'utilisateur est offensant" view_conversation: "Afficher la conversation" install: @@ -419,8 +336,7 @@ fr: description: "Configurez votre communauté Talk en quelques petites étapes." submit: "Commencer" add_organization: - description: "Veuillez nous indiquer le nom de votre organisation. Cela apparaî\ - tra dans les e-mails lors de l'invitation de nouveaux membres dans l'équipe." + description: "Veuillez nous indiquer le nom de votre organisation. Cela apparaîtra dans les e-mails lors de l'invitation de nouveaux membres dans l'équipe." label: "Nom de l'organisation" save: "Sauvegarder" create: @@ -431,13 +347,9 @@ fr: save: "Sauvegarder" permitted_domains: title: "Domaines autorisés" - description: "Entrez les domaines que vous souhaitez autoriser pour Talk, par\ - \ ex. vos environnements locaux, de déploiement et de production (ex localhost:\ - \ 3000, staging.domain.com, domain.com)." + description: "Entrez les domaines que vous souhaitez autoriser pour Talk, par ex. vos environnements locaux, de déploiement et de production (ex localhost:3000, staging.domain.com, domain.com)." submit: "Terminer l'installation" final: - description: "Merci d'avoir installé Talk ! Nous avons envoyé un e-mail pour\ - \ vérifier votre adresse électronique. Pendant que vous terminez la configuration,\ - \ vous pouvez commencer à engager vos lecteurs dès maintenant." + description: "Merci d'avoir installé Talk ! Nous avons envoyé un e-mail pour vérifier votre adresse électronique. Pendant que vous terminez la configuration, vous pouvez commencer à engager vos lecteurs dès maintenant." launch: "Lancer Talk" close: "Fermez cet installateur" diff --git a/services/i18n.js b/services/i18n.js index eff827cac..a8a160115 100644 --- a/services/i18n.js +++ b/services/i18n.js @@ -2,17 +2,19 @@ const has = require('lodash/has'); const get = require('lodash/get'); const yaml = require('yamljs'); + const es = yaml.load('./locales/es.yml'); const en = yaml.load('./locales/en.yml'); +const fr = yaml.load('./locales/fr.yml'); const accepts = require('accepts'); // default language let defaultLanguage = 'en'; let language = defaultLanguage; -const languages = ['en', 'es']; +const languages = ['en', 'es', 'fr']; -const translations = Object.assign(en, es); +const translations = Object.assign(en, es, fr); /** * Exposes a service object to allow translations. From d22f5215edf18d964cf6f6f534ba4fadde5c5af2 Mon Sep 17 00:00:00 2001 From: gaba Date: Fri, 9 Jun 2017 16:09:13 -0700 Subject: [PATCH 03/19] Adding french translation to the auth plugin. --- .../coral-plugin-auth/client/translations.yml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/plugins/coral-plugin-auth/client/translations.yml b/plugins/coral-plugin-auth/client/translations.yml index bc7f06759..189c3d9da 100644 --- a/plugins/coral-plugin-auth/client/translations.yml +++ b/plugins/coral-plugin-auth/client/translations.yml @@ -89,3 +89,47 @@ es: username: Nombre write_your_username: "Edita tu nombre" your_username: "Tu nombre aparece en cada comentario que publiques." +fr: + sign_in: + email_verify_cta: "Merci de vérifier votre adresse e-mail." + request_new_verify_email: "Demander un nouvel envoi d'e-mail :" + verify_email: "Merci d'avoir créé un compte ! Nous avons envoyé un courrier électronique à l'adresse que vous avez fournie pour vérifier votre adresse e-mail." + verify_email2: "Vous devez vérifier votre adresse e-mail avant de vous engager auprès de la communauté." + not_you: "Pas vous ?" + logged_in_as: "Connecté en tant que" + facebook_sign_in: "Connectez-vous avec Facebook" + facebook_sign_up: "Inscrivez-vous avec Facebook" + logout: "Se déconnecter" + sign_in: "Se connecter" + sign_in_to_join: "Connectez-vous pour participer à la conversation" + or: "Ou" + email: "Adresse e-mail" + password: "Mot de passe" + forgot_your_pass: "Mot de passe oublié ?" + need_an_account: "Besoin d'un compte ?" + register: "Inscription" + sign_up: "S'inscrire" + confirm_password: "Confirmez Le mot de passe" + username: "Nom d'utilisateur" + already_have_an_account: "Vous avez déjà un compte ?" + recover_password: "Récupérer le mot de passe" + email_in_use: "L'adresse e-mail est déjà utilisée" + email_or_username_in_use: "Adresse e-mail ou nom d'utilisateur déjà utilisé" + required_field: "Ce champ est obligatoire" + passwords_dont_match: "Les mots de passe ne correspondent pas." + special_characters: "Les noms d'utilisateur ne peuvent contenir que des lettres, des chiffres et \"_\" seulement" + sign_in_to_comment: "Connectez-vous pour commenter" + check_the_form: "Formulaire non valide. Veuillez vérifier les champs" + createdisplay: + check_the_form: "Formulaire non valide. Veuillez vérifier les champs" + continue: "Continuez avec le même nom d'utilisateur que sur Facebook" + error_create: "Erreur lors de la modification du nom d'utilisateur" + fake_comment_body: "Ceci est un exemple de commentaire. Les lecteurs peuvent partager leurs pensées et opinions avec les rédactions dans la section des commentaires." + fake_comment_date: "Il y a 1 minute" + if_you_dont_change_your_name: "Si vous ne modifiez pas votre nom d'utilisateur à cette étape, votre nom d'affichage Facebook apparaîtra à côté de tous vos commentaires." + required_field: "champs requis" + save: Sauvegarder + special_characters: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres et \"_\"" + username: "Nom d'utilisateur" + write_your_username: "Modifier votre nom d'utilisateur" + your_username: "Votre nom d'utilisateur apparaît sur chaque commentaire que vous publiez." From fd1f8b24c141fb3987b085762b5863b49b57f772 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Mon, 3 Jul 2017 19:33:33 +0700 Subject: [PATCH 04/19] Don't show popup when empty --- client/coral-framework/actions/auth.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index 05e078010..53d0f1212 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -7,8 +7,12 @@ import pym from '../services/PymConnection'; import {resetWebsocket} from 'coral-framework/services/client'; import t from 'coral-framework/services/i18n'; +import {isSlotEmpty} from 'plugin-api/beta/client/services'; export const showSignInDialog = () => (dispatch, getState) => { + if (isSlotEmpty('login')) { + return; + } const signInPopUp = window.open( '/embed/stream/login', 'Login', From f1899f2f4a0c63796851fd4a006a3981afff026a Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 01:09:12 +0700 Subject: [PATCH 05/19] Threading support --- .../src/components/Comment.js | 5 +- .../src/components/Stream.js | 5 +- .../src/constants/stream.js | 1 + .../src/containers/Stream.js | 69 ++++++++++++------- .../coral-embed-stream/src/graphql/utils.js | 42 ++++++----- 5 files changed, 74 insertions(+), 48 deletions(-) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 2e854633b..5e357e9b7 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -9,6 +9,7 @@ import {can} from 'coral-framework/services/perms'; import {TransitionGroup} from 'react-transition-group'; import cn from 'classnames'; import styles from './Comment.css'; +import {THREADING_LEVEL} from '../constants/stream'; import { BestButton, @@ -316,6 +317,7 @@ export default class Comment extends React.Component { postDontAgree, setActiveReplyBox, activeReplyBox, + loadMore, deleteAction, disableReply, maxCharCount, @@ -553,7 +555,7 @@ export default class Comment extends React.Component { charCountEnable={charCountEnable} maxCharCount={maxCharCount} setActiveReplyBox={setActiveReplyBox} - parentId={parentId || comment.id} + parentId={(depth < THREADING_LEVEL) ? comment.id : parentId} addNotification={addNotification} postComment={postComment} currentUser={currentUser} @@ -583,6 +585,7 @@ export default class Comment extends React.Component { deleteAction={deleteAction} addTag={addTag} removeTag={removeTag} + loadMore={loadMore} ignoreUser={ignoreUser} charCountEnable={charCountEnable} maxCharCount={maxCharCount} diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js index 0cfaf0368..4b04f5e7b 100644 --- a/client/coral-embed-stream/src/components/Stream.js +++ b/client/coral-embed-stream/src/components/Stream.js @@ -16,6 +16,7 @@ import IgnoredCommentTombstone from './IgnoredCommentTombstone'; import NewCount from './NewCount'; import {TransitionGroup} from 'react-transition-group'; import {forEachError} from 'coral-framework/utils'; +import {getTopLevelParent} from '../graphql/utils'; const hasComment = (nodes, id) => nodes.some((node) => node.id === id); @@ -169,9 +170,7 @@ class Stream extends React.Component { const open = asset.closedAt === null; // even though the permalinked comment is the highlighted one, we're displaying its parent + replies - const highlightedComment = comment && comment.parent - ? comment.parent - : comment; + const highlightedComment = comment && getTopLevelParent(comment); const banned = user && user.status === 'BANNED'; const temporarilySuspended = diff --git a/client/coral-embed-stream/src/constants/stream.js b/client/coral-embed-stream/src/constants/stream.js index 58004e877..5a8784a81 100644 --- a/client/coral-embed-stream/src/constants/stream.js +++ b/client/coral-embed-stream/src/constants/stream.js @@ -3,3 +3,4 @@ export const ADDTL_COMMENTS_ON_LOAD_MORE = 10; export const VIEW_ALL_COMMENTS = 'VIEW_ALL_COMMENTS'; export const ADD_COMMENT_CLASSNAME = 'ADD_COMMENT_CLASSNAME'; export const REMOVE_COMMENT_CLASSNAME = 'REMOVE_COMMENT_CLASSNAME'; +export const THREADING_LEVEL = 2; diff --git a/client/coral-embed-stream/src/containers/Stream.js b/client/coral-embed-stream/src/containers/Stream.js index 3491fc846..28947b77e 100644 --- a/client/coral-embed-stream/src/containers/Stream.js +++ b/client/coral-embed-stream/src/containers/Stream.js @@ -2,7 +2,7 @@ import React from 'react'; import {gql, compose} from 'react-apollo'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {ADDTL_COMMENTS_ON_LOAD_MORE} from '../constants/stream'; +import {ADDTL_COMMENTS_ON_LOAD_MORE, THREADING_LEVEL} from '../constants/stream'; import { withPostComment, withPostFlag, withPostDontAgree, withDeleteAction, withAddTag, withRemoveTag, withIgnoreUser, withEditComment, @@ -91,9 +91,7 @@ class StreamContainer extends React.Component { } loadNewReplies = (parent_id) => { - const comment = this.props.root.comment - ? this.props.root.comment.parent || this.props.root.comment // highlighted comment. - : this.props.root.asset.comments.nodes.filter((comment) => comment.id === parent_id)[0]; + const comment = findCommentInEmbedQuery(this.props.root, parent_id); return this.props.data.fetchMore({ query: LOAD_MORE_QUERY, @@ -153,20 +151,35 @@ class StreamContainer extends React.Component { } } +const nest = (def, level) => { + let result = ''; + for (let x = 0; x < level; x++) { + if (x === 0) { + result += def; + continue; + } + result = result.replace('...nest', def); + } + return result.replace('...nest', ''); +}; + const commentFragment = gql` fragment CoralEmbedStream_Stream_comment on Comment { id ...${getDefinitionName(Comment.fragments.comment)} - replyCount(excludeIgnored: $excludeIgnored) - replies(excludeIgnored: $excludeIgnored) { - nodes { - id - ...${getDefinitionName(Comment.fragments.comment)} + ${nest(` + replyCount(excludeIgnored: $excludeIgnored) + replies(excludeIgnored: $excludeIgnored) { + nodes { + id + ...${getDefinitionName(Comment.fragments.comment)} + ...nest + } + hasNextPage + startCursor + endCursor } - hasNextPage - startCursor - endCursor - } + `, THREADING_LEVEL)} } ${Comment.fragments.comment} `; @@ -205,16 +218,19 @@ const LOAD_MORE_QUERY = gql` nodes { id ...${getDefinitionName(Comment.fragments.comment)} - replyCount(excludeIgnored: $excludeIgnored) - replies(limit: 3, excludeIgnored: $excludeIgnored) { - nodes { - id - ...${getDefinitionName(Comment.fragments.comment)} + ${nest(` + replyCount(excludeIgnored: $excludeIgnored) + replies(limit: 3, excludeIgnored: $excludeIgnored) { + nodes { + id + ...${getDefinitionName(Comment.fragments.comment)} + ...nest + } + hasNextPage + startCursor + endCursor } - hasNextPage - startCursor - endCursor - } + `, THREADING_LEVEL)} } hasNextPage startCursor @@ -229,9 +245,12 @@ const fragments = { fragment CoralEmbedStream_Stream_root on RootQuery { comment(id: $commentId) @include(if: $hasComment) { ...CoralEmbedStream_Stream_comment - parent { - ...CoralEmbedStream_Stream_comment - } + ${nest(` + parent { + ...CoralEmbedStream_Stream_comment + ...nest + } + `, THREADING_LEVEL)} } asset(id: $assetId, url: $assetUrl) { id diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index eff1e2439..518f4b62f 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -1,21 +1,23 @@ import update from 'immutability-helper'; +import {THREADING_LEVEL} from '../constants/stream'; function applyToCommentsOrigin(root, callback) { if (root.comment) { - if (root.comment.parent) { - return update(root, { - comment: { - parent: { - $apply: (node) => callback(node), - }, - }, - }); + let comment = root.comment; + console.log(comment); + for (let depth = 0; depth <= THREADING_LEVEL; depth++) { + let changes = {$apply: (node) => node ? callback(node) : node}; + for (let i = 0; i < depth; i++) { + changes = {parent: changes}; + } + console.log(changes); + comment = update(comment, changes); } - return update(root, { - comment: { - $apply: (node) => callback(node), - }, - }); + + return { + ...root, + comment, + }; } return update(root, { asset: {$apply: (asset) => callback(asset)}, @@ -97,6 +99,13 @@ export function removeCommentFromEmbedQuery(root, id) { return applyToCommentsOrigin(root, (origin) => findAndRemoveComment(origin, id)); } +export function getTopLevelParent(comment) { + if (comment.parent) { + return getTopLevelParent(comment.parent); + } + return comment; +} + function findComment(nodes, callback) { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; @@ -119,12 +128,7 @@ export function findCommentInEmbedQuery(root, callbackOrId) { callback = (node) => node.id === callbackOrId; } if (root.comment) { - if (callback(root.comment)) { - return root.comment; - } - if (root.comment.parent && callback(root.comment.parent)) { - return root.comment.parent; - } + return findComment([getTopLevelParent(root.comment)], callback); } if (!root.asset.comments) { return false; From 3a2a4379b8bfc61c055c095c4817f5a6f714a610 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 00:51:59 +0700 Subject: [PATCH 06/19] Change to 4 levels --- client/coral-embed-stream/src/constants/stream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-embed-stream/src/constants/stream.js b/client/coral-embed-stream/src/constants/stream.js index 5a8784a81..2fe02d2ff 100644 --- a/client/coral-embed-stream/src/constants/stream.js +++ b/client/coral-embed-stream/src/constants/stream.js @@ -3,4 +3,4 @@ export const ADDTL_COMMENTS_ON_LOAD_MORE = 10; export const VIEW_ALL_COMMENTS = 'VIEW_ALL_COMMENTS'; export const ADD_COMMENT_CLASSNAME = 'ADD_COMMENT_CLASSNAME'; export const REMOVE_COMMENT_CLASSNAME = 'REMOVE_COMMENT_CLASSNAME'; -export const THREADING_LEVEL = 2; +export const THREADING_LEVEL = 3; From 31ab54d13c148404123514352d177ca6307ae4ac Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 21:32:33 +0700 Subject: [PATCH 07/19] First round styling --- .../src/components/Comment.css | 40 ++++++++++-- .../src/components/Comment.js | 65 +++++++++++-------- .../src/components/LoadMore.js | 18 +---- .../src/components/NewCount.js | 2 +- client/coral-embed-stream/style/default.css | 44 +++++++------ .../components/FlagButton.js | 20 +++--- .../coral-plugin-flags/components/styles.css | 7 ++ locales/en.yml | 6 +- locales/es.yml | 6 +- .../client/components/PermalinkButton.js | 8 +-- .../client/components/styles.css | 15 +++-- 11 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 client/coral-plugin-flags/components/styles.css diff --git a/client/coral-embed-stream/src/components/Comment.css b/client/coral-embed-stream/src/components/Comment.css index 4ff0586da..4c8a9fc86 100644 --- a/client/coral-embed-stream/src/components/Comment.css +++ b/client/coral-embed-stream/src/components/Comment.css @@ -1,11 +1,41 @@ -.Reply { - position: relative; +.root { + margin-top: 16px; + margin-left: 20px; margin-bottom: 15px; + position: relative; } -.Comment { - margin-bottom: 15px; - position: relative; +.rootLevel0 { + margin-left: 0px; +} + +.comment { + padding-left: 20px; +} + +.commentLevel0 { + padding-left: 0px; +} + +.commentLevel1 { + border-left: 3px #212121 solid; +} + +.commentLevel2 { + border-left: 2px #6a6a6a solid; +} + +.commentLevel3 { + border-left: 2px #9e9e9e solid; +} + +.commentLevel4 { + border-left: 2px #c1c1c1 solid; +} + +.highlightedComment { + padding-left: 20px; + border-left: 3px solid rgb(35,118,216); } .pendingComment { diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 5e357e9b7..b8b35e3fa 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -10,6 +10,8 @@ import {TransitionGroup} from 'react-transition-group'; import cn from 'classnames'; import styles from './Comment.css'; import {THREADING_LEVEL} from '../constants/stream'; +import merge from 'lodash/merge'; +import mapValues from 'lodash/mapValues'; import { BestButton, @@ -333,9 +335,12 @@ export default class Comment extends React.Component { const view = this.getVisibileReplies(); const {loadingState} = this.state; + const isReply = !!parentId; + const isPending = comment.id.indexOf('pending') >= 0; + const isHighlighted = highlighted === comment.id; const hasMoreComments = comment.replies && (comment.replies.hasNextPage || comment.replies.nodes.length > view.length); - const replyCount = this.hasIgnoredReplies() ? '' : comment.replyCount; + const moreRepliesCount = this.hasIgnoredReplies() ? -1 : comment.replyCount - view.length; const flagSummary = getActionSummary('FlagActionSummary', comment); const dontAgreeSummary = getActionSummary( 'DontAgreeActionSummary', @@ -348,11 +353,6 @@ export default class Comment extends React.Component { myFlag = dontAgreeSummary.find((s) => s.current_user); } - let commentClass = parentId - ? `reply ${styles.Reply}` - : `comment ${styles.Comment}`; - commentClass += comment.id.indexOf('pending') >= 0 ? ` ${styles.pendingComment}` : ''; - // call a function, and if it errors, call addNotification('error', ...) (e.g. to show user a snackbar) const notifyOnError = (fn, errorToMessage) => async function(...args) { @@ -388,7 +388,7 @@ export default class Comment extends React.Component { ); /** - * classNamesToAdd + * conditionClassNames * adds classNames based on condition * classnames is an array of objects with key as classnames and value as conditions * i.e: @@ -398,34 +398,43 @@ export default class Comment extends React.Component { * * This will add myClassName to comments tagged with STAFF TAG. * **/ - - const classNamesToAdd = commentClassNames.reduce((acc, className) => { - let res = []; - - // Adding classNames based on tags - Object.keys(className).forEach((cn) => { - const condition = className[cn]; - condition.tags.forEach((tag) => { - if (hasTag(comment.tags, tag)) { - res = [...res, cn]; - } - }); + const conditionalClassNames = + mapValues(merge({}, ...commentClassNames), (condition) => { + if (condition.tags) { + return condition.tags.some((tag) => hasTag(comment.tags, tag)); + } + return false; }); - // TODO: Compare rest of the comment obj to the condition if needed - - return [...acc, ...res]; - }, []); + const rootClassNames = [ + 'talk-stream-comment-wrapper', + `talk-stream-comment-wrapper-level-${depth}`, + styles.root, + styles[`rootLevel${depth}`], + { + ...conditionalClassNames, + [styles.enter]: this.state.animateEnter, + }, + ]; return (
-
+ {!isReply &&
}
{isStaff(comment.tags) ? Staff : null} @@ -601,7 +610,7 @@ export default class Comment extends React.Component {
{ if (!count) { - return t('framework.view_all_replies_unknown_number'); + return t('framework.show_all_replies'); } if (count === 1) { - return t('framework.view_reply'); + return t('framework.show_1_more_reply'); } - if (this.initialState) { - return t('framework.view_all_replies_initial', count); - } else { - return t('framework.view_all_replies', count); - } - } - - componentWillReceiveProps(nextProps) { - if (['success', 'error'].indexOf(nextProps.loadingState) >= 0) { - this.initialState = false; - } + return t('framework.show_x_more_replies', count); } render () { diff --git a/client/coral-embed-stream/src/components/NewCount.js b/client/coral-embed-stream/src/components/NewCount.js index 1c135ab9b..8f3b77dcb 100644 --- a/client/coral-embed-stream/src/components/NewCount.js +++ b/client/coral-embed-stream/src/components/NewCount.js @@ -3,7 +3,7 @@ import React, {PropTypes} from 'react'; import t from 'coral-framework/services/i18n'; const NewCount = ({count, loadMore}) => { - return
+ return
{ count ? { @@ -214,12 +219,3 @@ export default class FlagButton extends Component { ); } } - -const styles = { - flaggedIcon: { - color: '#F00' - }, - unflaggedIcon: { - color: 'inherit' - } -}; diff --git a/client/coral-plugin-flags/components/styles.css b/client/coral-plugin-flags/components/styles.css new file mode 100644 index 000000000..6de9df387 --- /dev/null +++ b/client/coral-plugin-flags/components/styles.css @@ -0,0 +1,7 @@ +.button { + margin: 5px 0px 5px 10px; +} + +.flaggedIcon { + color: #f00 +} diff --git a/locales/en.yml b/locales/en.yml index dce6f621b..44db5e1b8 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -235,9 +235,9 @@ en: success_bio_update: "Your biography has been updated" success_name_update: "Your username has been updated" success_update_settings: "The changes you have made have been applied to the comment stream on this article" - view_all_replies_unknown_number: "view all replies" - view_all_replies: "view {0} replies" - view_all_replies_initial: "view all {0} replies" + show_all_replies: Show all replies + show_1_more_reply: Show 1 more reply + show_x_more_replies: Show {0} more replies view_more_comments: "view more comments" view_reply: "view reply" from_settings_page: "From the Profile Page you can see your comment history." diff --git a/locales/es.yml b/locales/es.yml index 6a0334fcd..a6b1bc4cd 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -232,9 +232,9 @@ es: success_bio_update: "Tu biografia fue actualizada" success_name_update: "Tu nombre de usuario ha sido actualizado" success_update_settings: "La configuración de este articulo fue actualizada" - view_all_replies_unknown_number: "ver todas las respuestas" - view_all_replies: "ver {0} respuestas" - view_all_replies_initial: "ver todas las {0} respuestas" + show_all_replies: "Mostrar todas las respuestas" + show_1_more_reply: "Mostrar 1 respuesta más" + show_x_more_replies: "Mostrar {0} respuestas más" view_more_comments: "Ver más comentarios" view_reply: "ver respuesta" from_settings_page: "Desde la página de configuración puedes ver tu historia de comentarios." diff --git a/plugins/talk-plugin-permalink/client/components/PermalinkButton.js b/plugins/talk-plugin-permalink/client/components/PermalinkButton.js index fc8561bdc..55b98e5d8 100644 --- a/plugins/talk-plugin-permalink/client/components/PermalinkButton.js +++ b/plugins/talk-plugin-permalink/client/components/PermalinkButton.js @@ -66,11 +66,11 @@ export default class PermalinkButton extends React.Component { return (
- + @@ -89,7 +89,7 @@ export default class PermalinkButton extends React.Component {
diff --git a/plugins/talk-plugin-permalink/client/components/styles.css b/plugins/talk-plugin-permalink/client/components/styles.css index 56d069755..f14e87881 100644 --- a/plugins/talk-plugin-permalink/client/components/styles.css +++ b/plugins/talk-plugin-permalink/client/components/styles.css @@ -42,7 +42,13 @@ } .button { + margin: 5px 0px 5px 10px; + cursor: pointer; +} + +.copyButton { display: inline-block; + margin: 5px 10px 5px 0px; float: right; box-sizing: border-box; margin: 0; @@ -52,18 +58,19 @@ height: auto; padding: 2px; transition: background-color 0.4s ease; + cursor: pointer; } -.button:hover{ +.copyButton:hover{ color: black; } -.button.success { +.copyButton.success { background-color: #00897B; color: white; } -.button.failure { +.copyButton.failure { background-color: #FF5252; color: white; } @@ -74,4 +81,4 @@ .active { display: block; -} \ No newline at end of file +} From 524be1b86993ded4c1bea69b6103e3f4cecb163c Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 22:10:40 +0700 Subject: [PATCH 08/19] Allow customizing thread levels via TALK_THREADING_LEVEL env --- client/coral-embed-stream/src/constants/stream.js | 2 +- webpack.config.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/constants/stream.js b/client/coral-embed-stream/src/constants/stream.js index 2fe02d2ff..992767455 100644 --- a/client/coral-embed-stream/src/constants/stream.js +++ b/client/coral-embed-stream/src/constants/stream.js @@ -3,4 +3,4 @@ export const ADDTL_COMMENTS_ON_LOAD_MORE = 10; export const VIEW_ALL_COMMENTS = 'VIEW_ALL_COMMENTS'; export const ADD_COMMENT_CLASSNAME = 'ADD_COMMENT_CLASSNAME'; export const REMOVE_COMMENT_CLASSNAME = 'REMOVE_COMMENT_CLASSNAME'; -export const THREADING_LEVEL = 3; +export const THREADING_LEVEL = process.env.TALK_THREADING_LEVEL; diff --git a/webpack.config.js b/webpack.config.js index 130ced27b..c39726882 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -112,7 +112,8 @@ const config = { } }), new webpack.EnvironmentPlugin({ - 'TALK_PLUGINS_JSON': '{}' + 'TALK_PLUGINS_JSON': '{}', + 'TALK_THREADING_LEVEL': '3' }) ], resolveLoader: { From cfa7a74742d77307fa1f94d6c9bf16bd681ac189 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 22:22:52 +0700 Subject: [PATCH 09/19] Fix isSlotEmpty logic and handle empty plugin_config --- client/coral-framework/helpers/plugins.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/coral-framework/helpers/plugins.js b/client/coral-framework/helpers/plugins.js index bb21bef6c..ab5e3080e 100644 --- a/client/coral-framework/helpers/plugins.js +++ b/client/coral-framework/helpers/plugins.js @@ -12,17 +12,19 @@ import camelize from './camelize'; function getSlotComponents(slot) { const pluginConfig = getStore().getState().config.plugin_config; + + // Filter out components that have been disabled in `plugin_config` return flatten(plugins // Filter out components that have been disabled in `plugin_config` - .filter((o) => !pluginConfig[o.plugin] || !pluginConfig[o.plugin].disable_components) + .filter((o) => !pluginConfig || !pluginConfig[o.plugin] || !pluginConfig[o.plugin].disable_components) .filter((o) => o.module.slots[slot]) .map((o) => o.module.slots[slot])); } export function isSlotEmpty(slot) { - return !!getSlotComponents(slot).length; + return getSlotComponents(slot).length === 0; } /** From d155615102118f3f363d75c3d42a0482992e6be9 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 22:41:38 +0700 Subject: [PATCH 10/19] Add pending comment --- client/coral-embed-stream/src/components/Comment.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index b8b35e3fa..0e6201caf 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -432,6 +432,7 @@ export default class Comment extends React.Component { { [styles.pendingComment]: isPending, [styles.highlightedComment]: isHighlighted, + 'talk-stream-pending-comment': isPending, 'talk-stream-highlighted-comment': isHighlighted, } )} From 6d71bcbee96f359e04e7cb69c6fbe448d1aa8869 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 4 Jul 2017 22:56:58 +0700 Subject: [PATCH 11/19] Fix styling issues --- client/coral-embed-stream/style/default.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index b1d3a7f29..bd56cb748 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -450,7 +450,7 @@ button.comment__action-button[disabled], border-radius: 2px; } -.talk-load-more-replies .talk-load-more-button:hover { +.talk-load-more-replies .talk-load-more:hover button { background-color: #979797; color: white; } From f94c36e9c9e71dff81d3ab5a0c194e35970329eb Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Wed, 5 Jul 2017 11:43:18 +0100 Subject: [PATCH 12/19] Update version 2.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0040783a..382846cef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "2.2.0", + "version": "2.2.1", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "scripts": { From 693879647eccba05bf106ba06e075ed6f5fff473 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 5 Jul 2017 21:55:25 +0700 Subject: [PATCH 13/19] Cleanup --- .../src/components/Comment.js | 34 +++++++++---------- .../src/containers/Stream.js | 13 +------ .../coral-embed-stream/src/graphql/utils.js | 32 +++++++++++++++-- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 0e6201caf..7cc8b1480 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -406,7 +406,7 @@ export default class Comment extends React.Component { return false; }); - const rootClassNames = [ + const rootClassName = cn( 'talk-stream-comment-wrapper', `talk-stream-comment-wrapper-level-${depth}`, styles.root, @@ -415,28 +415,28 @@ export default class Comment extends React.Component { ...conditionalClassNames, [styles.enter]: this.state.animateEnter, }, - ]; + ); + + const commentClassName = cn( + 'talk-stream-comment', + `talk-stream-comment-level-${depth}`, + styles.comment, + styles[`commentLevel${depth}`], + { + [styles.pendingComment]: isPending, + [styles.highlightedComment]: isHighlighted, + 'talk-stream-pending-comment': isPending, + 'talk-stream-highlighted-comment': isHighlighted, + } + ); return (
{!isReply &&
} -
+
{isStaff(comment.tags) ? Staff : null} diff --git a/client/coral-embed-stream/src/containers/Stream.js b/client/coral-embed-stream/src/containers/Stream.js index 28947b77e..e52aa000f 100644 --- a/client/coral-embed-stream/src/containers/Stream.js +++ b/client/coral-embed-stream/src/containers/Stream.js @@ -21,6 +21,7 @@ import { insertCommentIntoEmbedQuery, removeCommentFromEmbedQuery, insertFetchedCommentsIntoEmbedQuery, + nest, } from '../graphql/utils'; const {showSignInDialog} = authActions; @@ -151,18 +152,6 @@ class StreamContainer extends React.Component { } } -const nest = (def, level) => { - let result = ''; - for (let x = 0; x < level; x++) { - if (x === 0) { - result += def; - continue; - } - result = result.replace('...nest', def); - } - return result.replace('...nest', ''); -}; - const commentFragment = gql` fragment CoralEmbedStream_Stream_comment on Comment { id diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index 518f4b62f..03d9fe02a 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -4,13 +4,11 @@ import {THREADING_LEVEL} from '../constants/stream'; function applyToCommentsOrigin(root, callback) { if (root.comment) { let comment = root.comment; - console.log(comment); for (let depth = 0; depth <= THREADING_LEVEL; depth++) { let changes = {$apply: (node) => node ? callback(node) : node}; for (let i = 0; i < depth; i++) { changes = {parent: changes}; } - console.log(changes); comment = update(comment, changes); } @@ -183,3 +181,33 @@ function findAndInsertFetchedComments(parent, comments, parent_id) { export function insertFetchedCommentsIntoEmbedQuery(root, comments, parent_id) { return applyToCommentsOrigin(root, (origin) => findAndInsertFetchedComments(origin, comments, parent_id)); } + +/** + * Nest a string in itself repeatly until `level` has been reached. + * + * Example: + * nest(` + * a + * ...nest + * b + * `, 2) + * + * Output: + * ` + * a + * a + * b + * b + * ` + */ +export function nest(document, level) { + let result = ''; + for (let x = 0; x < level; x++) { + if (x === 0) { + result += document; + continue; + } + result = result.replace('...nest', document); + } + return result.replace('...nest', ''); +} From b7c4dbd2246b439117f37c0a17e9fae23ea00d20 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 7 Jul 2017 17:27:05 +0700 Subject: [PATCH 14/19] Remove CommonJS style exports in framework --- client/coral-embed-stream/src/actions/stream.js | 2 +- client/coral-embed-stream/src/containers/Embed.js | 4 +++- client/coral-embed-stream/src/containers/Stream.js | 3 ++- client/coral-embed-stream/src/index.js | 2 +- client/coral-framework/actions/auth.js | 2 +- client/coral-framework/actions/index.js | 9 --------- client/coral-framework/actions/notification.js | 2 +- client/coral-framework/components/ClickOutside.js | 2 +- client/coral-framework/index.js | 10 ---------- client/coral-framework/reducers/auth.js | 2 +- .../services/{PymConnection.js => pym.js} | 2 +- client/coral-settings/containers/ProfileContainer.js | 2 +- 12 files changed, 13 insertions(+), 29 deletions(-) delete mode 100644 client/coral-framework/actions/index.js delete mode 100644 client/coral-framework/index.js rename client/coral-framework/services/{PymConnection.js => pym.js} (77%) diff --git a/client/coral-embed-stream/src/actions/stream.js b/client/coral-embed-stream/src/actions/stream.js index 9b5d94a9b..75c665315 100644 --- a/client/coral-embed-stream/src/actions/stream.js +++ b/client/coral-embed-stream/src/actions/stream.js @@ -1,4 +1,4 @@ -import {pym} from 'coral-framework'; +import pym from 'coral-framework/services/pym'; import * as actions from '../constants/stream'; export const setActiveReplyBox = (id) => ({type: actions.SET_ACTIVE_REPLY_BOX, id}); diff --git a/client/coral-embed-stream/src/containers/Embed.js b/client/coral-embed-stream/src/containers/Embed.js index bf05caf29..da7ca48fa 100644 --- a/client/coral-embed-stream/src/containers/Embed.js +++ b/client/coral-embed-stream/src/containers/Embed.js @@ -7,7 +7,9 @@ import branch from 'recompose/branch'; import renderComponent from 'recompose/renderComponent'; import {Spinner} from 'coral-ui'; -import {authActions, assetActions, pym} from 'coral-framework'; +import * as authActions from 'coral-framework/actions/auth'; +import * as assetActions from 'coral-framework/actions/asset'; +import pym from 'coral-framework/services/pym'; import {getDefinitionName} from 'coral-framework/utils'; import {withQuery} from 'coral-framework/hocs'; import Embed from '../components/Embed'; diff --git a/client/coral-embed-stream/src/containers/Stream.js b/client/coral-embed-stream/src/containers/Stream.js index 28947b77e..126c443ff 100644 --- a/client/coral-embed-stream/src/containers/Stream.js +++ b/client/coral-embed-stream/src/containers/Stream.js @@ -8,7 +8,8 @@ import { withAddTag, withRemoveTag, withIgnoreUser, withEditComment, } from 'coral-framework/graphql/mutations'; -import {notificationActions, authActions} from 'coral-framework'; +import * as authActions from 'coral-framework/actions/auth'; +import * as notificationActions from 'coral-framework/actions/notification'; import {editName} from 'coral-framework/actions/user'; import {setActiveReplyBox} from '../actions/stream'; import Stream from '../components/Stream'; diff --git a/client/coral-embed-stream/src/index.js b/client/coral-embed-stream/src/index.js index 16c510c29..f5be3922d 100644 --- a/client/coral-embed-stream/src/index.js +++ b/client/coral-embed-stream/src/index.js @@ -7,8 +7,8 @@ import './graphql'; import {addExternalConfig} from 'coral-embed-stream/src/actions/config'; import {getStore, injectReducers} from 'coral-framework/services/store'; import {getClient} from 'coral-framework/services/client'; +import pym from 'coral-framework/services/pym'; import AppRouter from './AppRouter'; -import {pym} from 'coral-framework'; import {loadPluginsTranslations, injectPluginsReducers} from 'coral-framework/helpers/plugins'; import reducers from './reducers'; diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index 53d0f1212..732a11ebe 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -3,7 +3,7 @@ import bowser from 'bowser'; import * as actions from '../constants/auth'; import * as Storage from '../helpers/storage'; import coralApi, {base} from '../helpers/request'; -import pym from '../services/PymConnection'; +import pym from '../services/pym'; import {resetWebsocket} from 'coral-framework/services/client'; import t from 'coral-framework/services/i18n'; diff --git a/client/coral-framework/actions/index.js b/client/coral-framework/actions/index.js deleted file mode 100644 index 65f7b87d3..000000000 --- a/client/coral-framework/actions/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import * as authActions from './auth'; -import * as assetActions from './asset'; -import * as notificationActions from './notification'; - -export default { - authActions, - assetActions, - notificationActions, -}; diff --git a/client/coral-framework/actions/notification.js b/client/coral-framework/actions/notification.js index d77a3a16c..57a7950f5 100644 --- a/client/coral-framework/actions/notification.js +++ b/client/coral-framework/actions/notification.js @@ -1,4 +1,4 @@ -import pym from '../services/PymConnection'; +import pym from '../services/pym'; import * as actions from '../constants/notification'; export const addNotification = (notifType, text) => { diff --git a/client/coral-framework/components/ClickOutside.js b/client/coral-framework/components/ClickOutside.js index e13ef4472..5348a9af7 100644 --- a/client/coral-framework/components/ClickOutside.js +++ b/client/coral-framework/components/ClickOutside.js @@ -1,7 +1,7 @@ import {Component, cloneElement, Children} from 'react'; import PropTypes from 'prop-types'; import {findDOMNode} from 'react-dom'; -import {pym} from 'coral-framework'; +import pym from 'coral-framework/services/pym'; export default class ClickOutside extends Component { static propTypes = { diff --git a/client/coral-framework/index.js b/client/coral-framework/index.js deleted file mode 100644 index 5cd9d6174..000000000 --- a/client/coral-framework/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import pym from './services/PymConnection'; -import actions from './actions'; - -// TODO (bc): Deprecate old actions. Spreading actions is now needed. - -export default { - pym, - actions, - ...actions -}; diff --git a/client/coral-framework/reducers/auth.js b/client/coral-framework/reducers/auth.js index 7ab12cf53..92d676abe 100644 --- a/client/coral-framework/reducers/auth.js +++ b/client/coral-framework/reducers/auth.js @@ -1,6 +1,6 @@ import {Map, fromJS} from 'immutable'; import * as actions from '../constants/auth'; -import {pym} from 'coral-framework'; +import pym from 'coral-framework/services/pym'; const initialState = Map({ isLoading: false, diff --git a/client/coral-framework/services/PymConnection.js b/client/coral-framework/services/pym.js similarity index 77% rename from client/coral-framework/services/PymConnection.js rename to client/coral-framework/services/pym.js index 6c492f2b8..bb5d90a0e 100644 --- a/client/coral-framework/services/PymConnection.js +++ b/client/coral-framework/services/pym.js @@ -1,4 +1,4 @@ -import Pym from '../../../node_modules/pym.js'; +import Pym from 'pym.js'; const pym = new Pym.Child({polling: 100}); export default pym; diff --git a/client/coral-settings/containers/ProfileContainer.js b/client/coral-settings/containers/ProfileContainer.js index 5e343e72f..a4cb9459f 100644 --- a/client/coral-settings/containers/ProfileContainer.js +++ b/client/coral-settings/containers/ProfileContainer.js @@ -5,7 +5,7 @@ import {bindActionCreators} from 'redux'; import {withStopIgnoringUser} from 'coral-framework/graphql/mutations'; -import {link} from 'coral-framework/services/PymConnection'; +import {link} from 'coral-framework/services/pym'; import NotLoggedIn from '../components/NotLoggedIn'; import IgnoredUsers from '../components/IgnoredUsers'; import {Spinner} from 'coral-ui'; From af3cd8aa68dc64d39f17260ba16598e6de775e8b Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Fri, 7 Jul 2017 15:09:25 +0100 Subject: [PATCH 15/19] Update version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 382846cef..0fe387185 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "2.2.1", + "version": "2.3.0", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "scripts": { From 787c00325d75dcaa6f17bdd1e42feabe84d30c0e Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 7 Jul 2017 08:40:18 -0600 Subject: [PATCH 16/19] Added new cli-settings --- bin/cli | 11 +++++++-- bin/cli-settings | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100755 bin/cli-settings diff --git a/bin/cli b/bin/cli index 33560c53b..52d67c9af 100755 --- a/bin/cli +++ b/bin/cli @@ -9,13 +9,17 @@ const program = require('./commander'); program .command('serve', 'serve the application') + .command('settings', 'interact with the application settings') .command('assets', 'interact with assets') .command('setup', 'setup the application') .command('jobs', 'work with the job queues') .command('token', 'work with the access tokens') .command('users', 'work with the application auth') .command('migration', 'provides utilities for migrating the database') - .command('plugins', 'provides utilities for interacting with the plugin system') + .command( + 'plugins', + 'provides utilities for interacting with the plugin system' + ) .parse(process.argv); /** @@ -25,7 +29,10 @@ program * labled with the PID written out by the parent process. */ process.once('exit', () => { - if ((program.runningCommand.killed === false) && (program.runningCommand.exitCode === null)) { + if ( + program.runningCommand.killed === false && + program.runningCommand.exitCode === null + ) { program.runningCommand.kill('SIGINT'); } }); diff --git a/bin/cli-settings b/bin/cli-settings new file mode 100755 index 000000000..f8768046c --- /dev/null +++ b/bin/cli-settings @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +const program = require('./commander'); +const inquirer = require('inquirer'); +const mongoose = require('../services/mongoose'); +const SettingsService = require('../services/settings'); +const util = require('./util'); + +// Register the shutdown criteria. +util.onshutdown([() => mongoose.disconnect()]); + +/** + * Change the organization name + */ +async function changeOrgName() { + try { + let settings = await SettingsService.retrieve(); + + let {organizationName} = await inquirer.prompt([ + { + name: 'organizationName', + message: 'Organization Name', + default: settings.organizationName + } + ]); + + if (settings.organizationName !== organizationName) { + settings.organizationName = organizationName; + + await SettingsService.update(settings); + + console.log('Settings were updated.'); + } else { + console.log('No update needed, no change was made.'); + } + } catch (err) { + console.error(err); + util.shutdown(1); + } + + util.shutdown(); +} + +//============================================================================== +// Setting up the program command line arguments. +//============================================================================== + +program + .command('change-org-name') + .description('change the organization name') + .action(changeOrgName); + +program.parse(process.argv); + +// If there is no command listed, output help. +if (!process.argv.slice(2).length) { + program.outputHelp(); + util.shutdown(); +} From 23573501bdfc7edc828eb9000bb1d5fa6d30a73e Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 7 Jul 2017 08:57:56 -0600 Subject: [PATCH 17/19] Configured redis to flush before each test and changed default test redis database --- config.js | 27 ++++++++++++++++++++------- test/helpers/redis.js | 15 +++++++++++++++ test/server/redis.js | 3 +++ 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 test/helpers/redis.js create mode 100644 test/server/redis.js diff --git a/config.js b/config.js index 02f95d070..ce8931235 100644 --- a/config.js +++ b/config.js @@ -29,7 +29,7 @@ const CONFIG = { // JWT_ISSUER is the value for the issuer for the tokens that will be verified // when decoding. If `JWT_ISSUER` is not in the environment, then it will try // `TALK_ROOT_URL`, otherwise, it will be undefined. - JWT_ISSUER: process.env.TALK_JWT_ISSUER || process.env.TALK_ROOT_URL || undefined, + JWT_ISSUER: process.env.TALK_JWT_ISSUER || process.env.TALK_ROOT_URL, // JWT_EXPIRY is the time for which a given token is valid for. JWT_EXPIRY: process.env.TALK_JWT_EXPIRY || '1 day', @@ -91,7 +91,9 @@ const CONFIG = { if (process.env.NODE_ENV === 'test' && !CONFIG.JWT_SECRET) { CONFIG.JWT_SECRET = 'keyboard cat'; } else if (!CONFIG.JWT_SECRET) { - throw new Error('TALK_JWT_SECRET must be provided in the environment to sign/verify tokens'); + throw new Error( + 'TALK_JWT_SECRET must be provided in the environment to sign/verify tokens' + ); } //------------------------------------------------------------------------------ @@ -108,7 +110,7 @@ if (process.env.NODE_ENV === 'test' && !CONFIG.MONGO_URL) { // Reset the redis url in the event it hasn't been overrided and we are in a // testing environment. if (process.env.NODE_ENV === 'test' && !CONFIG.REDIS_URL) { - CONFIG.REDIS_URL = 'redis://localhost'; + CONFIG.REDIS_URL = 'redis://localhost/1'; } //------------------------------------------------------------------------------ @@ -119,10 +121,15 @@ if (process.env.NODE_ENV === 'test' && !CONFIG.REDIS_URL) { * This is true when the recaptcha secret is provided and the Recaptcha feature * is to be enabled. */ -CONFIG.RECAPTCHA_ENABLED = CONFIG.RECAPTCHA_SECRET && CONFIG.RECAPTCHA_SECRET.length > 0 && - CONFIG.RECAPTCHA_PUBLIC && CONFIG.RECAPTCHA_PUBLIC.length > 0; +CONFIG.RECAPTCHA_ENABLED = + CONFIG.RECAPTCHA_SECRET && + CONFIG.RECAPTCHA_SECRET.length > 0 && + CONFIG.RECAPTCHA_PUBLIC && + CONFIG.RECAPTCHA_PUBLIC.length > 0; if (!CONFIG.RECAPTCHA_ENABLED) { - console.warn('Recaptcha is not enabled for login/signup abuse prevention, set TALK_RECAPTCHA_SECRET and TALK_RECAPTCHA_PUBLIC to enable Recaptcha.'); + console.warn( + 'Recaptcha is not enabled for login/signup abuse prevention, set TALK_RECAPTCHA_SECRET and TALK_RECAPTCHA_PUBLIC to enable Recaptcha.' + ); } //------------------------------------------------------------------------------ @@ -138,7 +145,13 @@ if (!CONFIG.RECAPTCHA_ENABLED) { ]; if (requiredProps.some((prop) => !CONFIG[prop])) { - console.warn(`${requiredProps.map((v) => `TALK_${v}`).join(', ')} should be defined in the environment if you would like to send password reset emails from Talk`); + console.warn( + `${requiredProps + .map((v) => `TALK_${v}`) + .join( + ', ' + )} should be defined in the environment if you would like to send password reset emails from Talk` + ); } } diff --git a/test/helpers/redis.js b/test/helpers/redis.js new file mode 100644 index 000000000..02ab81b51 --- /dev/null +++ b/test/helpers/redis.js @@ -0,0 +1,15 @@ +const {createClient} = require('../../services/redis'); + +// Create a redis client to use for clearing the database. +const client = createClient(); + +module.exports.clearDB = () => + new Promise((resolve, reject) => + client.flushdb((err) => { + if (err) { + return reject(err); + } + + return resolve(); + }) + ); diff --git a/test/server/redis.js b/test/server/redis.js new file mode 100644 index 000000000..529548918 --- /dev/null +++ b/test/server/redis.js @@ -0,0 +1,3 @@ +const redis = require('../helpers/redis'); + +beforeEach(() => redis.clearDB()); From 55e70dfbec1f6cb0456c81f841239757cc6e543e Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Mon, 10 Jul 2017 22:13:04 +0700 Subject: [PATCH 18/19] Fix perma view live updates --- client/coral-embed-stream/src/graphql/utils.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index 03d9fe02a..523cc571f 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -1,10 +1,18 @@ import update from 'immutability-helper'; -import {THREADING_LEVEL} from '../constants/stream'; +function determineCommentDepth(comment) { + let depth = 0; + let cur = comment; + while (cur.parent) { + cur = cur.parent; + depth++; + } + return depth; +} function applyToCommentsOrigin(root, callback) { if (root.comment) { let comment = root.comment; - for (let depth = 0; depth <= THREADING_LEVEL; depth++) { + for (let depth = 0; depth <= determineCommentDepth(comment); depth++) { let changes = {$apply: (node) => node ? callback(node) : node}; for (let i = 0; i < depth; i++) { changes = {parent: changes}; From a2dabcac0e5e63cbd4a66a966cf69f2a6a4ce26c Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Jul 2017 01:26:25 +0700 Subject: [PATCH 19/19] Hide action labels on mobile --- client/coral-embed-stream/style/default.css | 11 ----------- client/coral-plugin-replies/ReplyButton.css | 5 +++++ client/coral-plugin-replies/ReplyButton.js | 9 ++++++--- plugins/coral-plugin-like/client/LikeButton.js | 4 +++- plugins/coral-plugin-like/client/styles.css | 6 ++++++ plugins/coral-plugin-love/client/LoveButton.js | 4 +++- plugins/coral-plugin-love/client/styles.css | 6 ++++++ plugins/coral-plugin-respect/client/RespectButton.js | 4 ++-- plugins/coral-plugin-respect/client/styles.css | 6 ++++++ 9 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 client/coral-plugin-replies/ReplyButton.css diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index bd56cb748..3038e0da4 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -459,14 +459,3 @@ button.comment__action-button[disabled], width: initial; } - -@media (min-device-width : 300px) and (max-device-width : 420px) { - .commentActionsLeft.comment__action-container .coral-plugin-replies-reply-button { - visibility: collapse; - margin-left: -30px; - } - - .commentActionsLeft.comment__action-container .coral-plugin-replies-reply-button .coral-plugin-replies-icon { - visibility: visible; - } -} diff --git a/client/coral-plugin-replies/ReplyButton.css b/client/coral-plugin-replies/ReplyButton.css new file mode 100644 index 000000000..4f71e6630 --- /dev/null +++ b/client/coral-plugin-replies/ReplyButton.css @@ -0,0 +1,5 @@ +@media (max-width: 425px) { + .label { + display: none; + } +} diff --git a/client/coral-plugin-replies/ReplyButton.js b/client/coral-plugin-replies/ReplyButton.js index a66e3c156..4641ae02d 100644 --- a/client/coral-plugin-replies/ReplyButton.js +++ b/client/coral-plugin-replies/ReplyButton.js @@ -2,16 +2,19 @@ import React, {PropTypes} from 'react'; import t from 'coral-framework/services/i18n'; -import classnames from 'classnames'; +import cn from 'classnames'; +import styles from './ReplyButton.css'; const name = 'coral-plugin-replies'; const ReplyButton = ({onClick}) => { return ( diff --git a/plugins/coral-plugin-like/client/LikeButton.js b/plugins/coral-plugin-like/client/LikeButton.js index 7d17ef056..34b5e40f2 100644 --- a/plugins/coral-plugin-like/client/LikeButton.js +++ b/plugins/coral-plugin-like/client/LikeButton.js @@ -45,7 +45,9 @@ class LikeButton extends React.Component { className={cn(styles.button, {[styles.liked]: alreadyReacted}, `${plugin}-button`)} onClick={this.handleClick} > - {t(alreadyReacted ? 'coral-plugin-like.liked' : 'coral-plugin-like.like')} + + {t(alreadyReacted ? 'coral-plugin-like.liked' : 'coral-plugin-like.like')} + {count > 0 && count} diff --git a/plugins/coral-plugin-like/client/styles.css b/plugins/coral-plugin-like/client/styles.css index cb372fa47..b44c170e3 100644 --- a/plugins/coral-plugin-like/client/styles.css +++ b/plugins/coral-plugin-like/client/styles.css @@ -23,3 +23,9 @@ } } } + +@media (max-width: 425px) { + .label { + display: none; + } +} diff --git a/plugins/coral-plugin-love/client/LoveButton.js b/plugins/coral-plugin-love/client/LoveButton.js index 7450ad668..d67160773 100644 --- a/plugins/coral-plugin-love/client/LoveButton.js +++ b/plugins/coral-plugin-love/client/LoveButton.js @@ -45,7 +45,9 @@ class LoveButton extends React.Component { className={cn(styles.button, {[styles.loved]: alreadyReacted}, `${plugin}-button`)} onClick={this.handleClick} > - {t(alreadyReacted ? 'coral-plugin-love.loved' : 'coral-plugin-love.love')} + + {t(alreadyReacted ? 'coral-plugin-love.loved' : 'coral-plugin-love.love')} + {count > 0 && count} diff --git a/plugins/coral-plugin-love/client/styles.css b/plugins/coral-plugin-love/client/styles.css index e16e17ca4..ac5a86370 100644 --- a/plugins/coral-plugin-love/client/styles.css +++ b/plugins/coral-plugin-love/client/styles.css @@ -23,3 +23,9 @@ } } } + +@media (max-width: 425px) { + .label { + display: none; + } +} diff --git a/plugins/coral-plugin-respect/client/RespectButton.js b/plugins/coral-plugin-respect/client/RespectButton.js index 9bc556b67..878525051 100644 --- a/plugins/coral-plugin-respect/client/RespectButton.js +++ b/plugins/coral-plugin-respect/client/RespectButton.js @@ -45,11 +45,11 @@ class RespectButton extends React.Component { className={cn(styles.button, {[styles.respected]: alreadyReacted}, `${plugin}-button`)} onClick={this.handleClick} > - + {t(alreadyReacted ? 'coral-plugin-respect.respected' : 'coral-plugin-respect.respect')} - {count > 0 && count} + {count > 0 && count}
); diff --git a/plugins/coral-plugin-respect/client/styles.css b/plugins/coral-plugin-respect/client/styles.css index f0b780b86..d08d648c3 100644 --- a/plugins/coral-plugin-respect/client/styles.css +++ b/plugins/coral-plugin-respect/client/styles.css @@ -28,3 +28,9 @@ .icon { padding: 0 5px; } + +@media (max-width: 425px) { + .label { + display: none; + } +}