deby
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # c3Lingo shift assignment + Fahrplan translation tool The goal of this tool is to: - Create translator shifts from the Fahrplan - Allow translators to express interest in a given shift - Assign translators to shifts - Generate the list of completed shifts to import into engelsystem - Publicize which talks will be translated to which language via an API - Offer a translation of the name of the talks that will be translated via an API - The API can be used by social media or Fahrplan and apps that use it - An ical for translators to make sure no one misses their shifts Bonus: - Auto-check of username validity when signing up by calling EngelSystem - Public page to see translated talks with links to streams, proper credit to translators, etc. - Internal cheatsheet view for talks (Intros, Links, Numbers, Files, etc.) - Include files from file drop (or implement file drop functionality) - Link with engelsystem automatically - Auto tweets/toots for upcoming talks - Stats view - Filters (Past / Current / Future, Day, Booth, Language, Room, Needs translation for field/language) - Translate bios of speakers - Comments under talks For context, and after discussing with Frab/Fahrplan developers, it has been decided that we would provide a web API to share our translations. Once that's ready, the Fahrplan API, which is already aggregating data from various sources, could integrate our content. This decision aligns with recent shift in mindset towards more decentralization of data, rather then centralization (all stored in Frab's db). ### Technologies and dependencies Django has been decided because multiple participants in the Tech mumble work with it, and Python is overall easier to read for beginners. No mobile app needed, as long as the web app is mobile friendly. | | Backend | Frontend | Design | External | |-|---------|----------|--------|----------| | Main | Django | jQuery | LessCSS | | | Extra | iCal lib (tbd), django-bootstrap-form | Bower | Bootstrap, FontAwesome | PoEditor | ### Design We mentioned using the design chart of 31c3 as our baseline for the design of this tool and any other public communication about c3lingo (including social media). https://gitea.see-base.de/C3SIGN/31c3-design/ Tests using "Power" font, TeX Gyre Adventor font, or handmade shapes: [![](https://i.imgur.com/wNXSwCbt.png)](https://i.imgur.com/wNXSwCb.png) [![](https://i.imgur.com/npXangzt.png)](https://i.imgur.com/npXangz.png) [![](https://i.imgur.com/RfGa9Dot.png)](https://i.imgur.com/RfGa9Do.png) [![](https://i.imgur.com/ybEYKy3t.png)](https://i.imgur.com/ybEYKy3.png) [![](https://i.imgur.com/pZeFsyit.png)](https://i.imgur.com/pZeFsyi.png) [![](https://i.imgur.com/pJnOfdXt.png)](https://i.imgur.com/pJnOfdX.png) [![](https://i.imgur.com/tg6XFQ2t.png)](https://i.imgur.com/tg6XFQ2.png) [![](https://i.imgur.com/AJJ7j8it.png)](https://i.imgur.com/AJJ7j8i.png) - [x] Graphic identity has been designed ### Database A lot of fields retrieved from the Fahrplan are purposefully permissive (can be blank/null, unlimited char space). The idea is to keep it simple and only "cache" from Fahrplan what is useful to display to translators. The API should also only expose what is not in the Fahrplan + references (ids, codenames). Naming should be consistent with [Fahrplan API](https://fahrplan.events.ccc.de/congress/2019/Fahrplan/schedule.json) and [Frab](https://github.com/frab/frab). Tables: - [Language](#Language) - [Conference](#Conference) - [Talk](#Talk) - [Translation](#Translation) - [Translator](#Translator) - [Translator speaks](#Translator-speaks) - [Booth](#Booth) - [Shift](#Shift) - [Shift assignment](#Shift-assignment) ##### Language Lists the languages we support. Editable by staff only. | Field | Details | Example | Notes | |-------|---------|---------|-------| | Code | CharField, 8 | de | Follow RFC 3066 (like Django does) or ISO 639-3 for signed languages | | Name EN | CharField, 100 | "German" | Used mostly by our team | | Name | CharField, 100 | "Deutsch" | For presentation to end users. Use a name users of the language will be most likely to search for. | Where possible (spoken languages) we should follow the [language list provided by Django]([Choices](https://github.com/django/django/blob/master/django/conf/global_settings.py#L51)). ##### Conference | Field | Details | Example | Notes | |-------|---------|---------|-------| | Acronym | CharField 100, unique, required | 36c3 | | | Name | TextField, null *(defaults to acronym)* | `36th Chaos Communication Congress` | | | Image URL | TextField, blank | | | | Start date | DateField, null | | | | End date | DateField, null | | | | Fahrplan version | Textfield | | The latest version of the Fahrplan JSON we imported | ##### Talk Called "Event" in frab, but everyone talks about "Talk" in c3lingo so I used that. | Field | Details | Notes | |-------|---------|-------| | Conference | ForeignKey(Conference) | | | Fahrplan ID | CharField, 100, unique | unique_together with Conference | | Guid | TextField, blank | | | Title | TextField, blank | From Fahrplan, not translated | | Subtitle | TextField, blank | From Fahrplan, not translated | | Abstract | TextField, blank | From Fahrplan, not translated | | Description | TextField, blank | From Fahrplan, not translated | | Logo URL | TextField, blank | | | Language | ForeignKey(Language) | Original language | | Room | TextField, blank | | | Length | PositiveIntegerField, null, in seconds | | | Start date | DateField, null | | | End date | DateField, null | | | Type | TextField, blank | | | Speakers | TextField, blank, *comma-separated usernames from `persons`* | | ```python @property def slug(self): return '{conference_name}-{fahrplan_id}-{name}'.format( conference_name=self.conference.acronym, fahrplan_id=self.fahrplan_id, name=parameterize*(self.name), ) @property def watch_url(self): return 'https://media.ccc.de/v/{slug}'.format(slug=self.slug) @property def slides_url(self): return 'https://speakers.c3lingo.org/talks/{guid}/'.format(self.guid) ``` *[About parameterize](https://apidock.com/rails/String/parameterize) - [source](https://github.com/rails/rails/blob/08304732380773e907bc21e5023c0a32c1e9ea71/activesupport/lib/active_support/inflector/transliterate.rb#L121) ##### Translation This represents the translation of a property of a talk (title, subtitle, abstract, description). | Field | Details | Example | |-------|---------|---------| | User | ForeignKey(User), null | | Talk | ForeignKey(Talk), related_name='translations' | | | Field | CharField, 100, required | `name` | | Language | ForeignKey(Language), required | `de` | | Value | TextField, required, blank | "Die Bremsen kreischten fürchterlich" | - unique_together = `(talk, field, language)` ##### Translator Represents a translation angel. Note: User is a model that already exists in Django and already contains username, email, hashed password, and more. The "Contact Info" may duplicate the email address, but the Email field in User is only visible by staff, users should be prompted to add their email to Contact Info as well if comfortable during signup. DECT too. | Field | Details | Notes | |-------|---------|-------| | User | OneToOneField(User) | | | Confirmed by | ForeignKey(User), null | Can't login when not confirmed | | Bio | TextField, blank | Allow Markdown | | Contact info | TextField, blank | Visible to other translators. Example: your email address, phone number, Twitter @, Telegram, etc. | | Secret token | CharField(128) | Used to authenticate requests for the iCal URL. User can regenerate a new random secret token at any time. | ```python import hashlib @property def avatar_url(self): return 'https://www.gravatar.com/avatar/{}'.format( hashlib.md5(self.user.email.lower()).hexdigest(), ) ``` ##### Translator speaks What Languages a Translator can translate to/from. Editable by each translator for themselves. | Field | Details | |-------|---------| | User | ForeignKey(User), required | | Language | ForeignKey(Language), required | ##### Booth Represents a translation booth that contains a console. | Field | Details | Notes | |-------|---------|-------| | Room | TextField, required | | | Name | TextField, required | | | DECT | CharField(30), blank | | | DesiredOccupancy | Integer, required | How many translators are needed to translate a talk in this booth | | MaxOccupancy | Integer, required | How many translators can work in this booth maximum | ##### Shift A Shift is an opportunity for a number of Translators to translate a given Talk in a given Booth. | Field | Details | Notes | |-------|---------|-------| | Booth | ForeignKey(Booth) | | | Talk | ForeignKey(Talk), required | | | Language | ForeignKey(language), null | null means the shift's language is not defined yet (e.g. 2nd booth, it could become fr/es/... based on volunteers)| ##### Shift assignement Represents a Translator volunteering for a Shift. Any translator can waitlist themselves for a shift. Only staff can confirm (set waitlist to false). Only staff can set/unset the "freeloaded" status. | Field | Details | Notes | |-------|---------|-------| | Shift | ForeignKey(Shift), required | | | User | ForeignKey(User), required | | | Is waitlist | BooleanField(default=True) | | | Freeloaded | BooleanField(default=False) | In EngelSystem, "freeloaded" means the angel did not show up. Hours should not be counted. | | Comment | TextField, blank | User-editable free comment, e.g. to express why they are a good fit for this talk | ### API `api.c3lingo.org` `GET /translations/{conference_acronym}/` ```json { "acronym": "36c3", "updated": "2020-12-28T14:03:12+08:00", "fahrplan_version": "mirror the version of the fahrplan last used to generate this", "talks": [ { "fahrplan_id": "11223", "watch_url": "https://media.ccc.de/v/36c3-10991-science_for_future", "live_translators": { "en": [ { "username": "john89", "avatar": "https://www.gravatar.com/avatar/d64292036113c3e74f08fdf01055a8a7", "bio": "I hope you enjoy my translations. Follow me on [Twitter](https://twitter.com/john89). Thank you!" }, { ... } ], "fr": [ ... ] }, "translations": { "title": { "en": { "translation": "The brakes screeched terribly", "translator": { ... } }, "fr": { ... }, "it": { ... } }, "subtitle": { ... }, "abstract": { ... }, "description": { ... } } }, { ... } ], } ``` API FAQ: * Should this be searchable? E.g. filter by room, language, day/timerange? * Probably no: it's easier to just just dump everything cached in a big json static file, updated once in a while, and let clients filter things themselves * Documentation? * With a single endpoint and by keeping fields simple, I don't think we would need to publish a full documentation, besides just saying it exists and link to it. * User profiles get repeated a lot? * We considered returning just usernames, and have profiles at the end of the JSON file, but we prefer duplicating the profiles because we think by having them closer to the rest of the data, it's more likely developers will see them and want to use them, which means a higher chance for our translators to be properly credited. ### Ical `GET /user/{username}/schedule.ics?secret_token=xxxxxxx` ``` ical file of all the shifts a user is assigned to, or waitlisted for. The event title is something like: [en->de] [waitlisted] How to hack robots (Hall A) Events include: - start time xx minutes before the talk - location (room and booth) with link to our wiki on how to navigate there (or c3nav) - description & links to the talk info - info about other translators, including contact info ``` ### Views - [x] Basics: - [x] `/signup/` Signup (have to fill details in `Translator` table when signin up) - [x] `/login/` Login (when confirmed)/Logout/Forgot password - [x] `/conferences/` List of conferences - [x] Index`/`: - [x] If a conference is ongoing, starts soon, or ends soon: - [x] Redirects to `/conferences/{acronym}/` - Else: - [x] Redirects to `/conferences/` - [ ] List of talks per conferences: `/conferences/{acronym}/` - [ ] See shifts per talk - [ ] Insert self in talk's waitlist when interested - [ ] Save translation of talk details in supported languages - [ ] Talks view with staff privileges: `/conferences/{acronym}/` - [ ] Set/unset translators as waitlisted - [ ] Add translator to a shift (waitlisted or not, defaults to not) - [ ] Set/unset translators as freeloaded - [ ] Add/delete/edit shifts per talk - [ ] User `/user/{username}/` - [ ] View a user's profile (bio, shifts, languages, ContactInfo) - [ ] Staff can view the registration email, freeloaded status for shifts - [ ] Settings `/user/{username}/settings/` - [ ] Set which language(s) you can speak - [ ] Regenerate a new SecretToken - [ ] Staff configuration: `/configurations/` - [ ] Add/edit languages - [ ] Add/edit list of booths - [ ] Export shifts for Engelsystem - [ ] Force refresh list of talks from Fahrplan ### To do 1. [x] Pre-development - [x] Create repository 2. [ ] Development - [x] Design database - [ ] Write script to import list of talks from Fahrplan - [ ] Add API routes to get translations details and translators - [x] Basic authentication - [ ] Permissions sytem - [ ] Views 5. [ ] Post-development - [ ] Deploy to instance - [ ] Setup cron for auto update from Fahrplan - [ ] Setup cron for auto caching of API - [ ] Setup domain or sub-domain (c3lingo.org) 6. [ ] Bonus # Appendix ### Questions - Name of this project? - "Portal"/"Hub"? "shifts.c3lingo.org"? - c3lingo INSTANT - Interpreter's New Schedule Translation + Assignment Negotiation Tool - Self assign, or only show interest then confirm by someone? Both options, configurable? - Is there an OAuth integration in EngelSystem we could use to login to our own tool (to avoid having to double accept newcomers)? -- no there isn't :( - We would need some layer on Javascript to refresh/keep the page updated when doing shift assignments. Look into websocket? Is it critical, maybe we could let people refresh the page manually? - Consider the pros and cons of an extra table vs use a [custom User model](https://docs.djangoproject.com/fr/2.2/topics/auth/customizing/#specifying-a-custom-user-model)? - Should we have per-booth rules so in booth2 anyone can confirm themselves? Issues in this doc: * Need to figure out how to deal with Fahrplan talk IDs (do we want the ID, the GUID, both?) * Maybe need to create a model to represent Rooms ### Links - Script to parse current pads: https://github.com/c3lingo/tootTranslations/tree/master/toottranslations ### People - @db0company point of contact for this project - @erdgeist Fahrplan / frab point of contact - @bluewhobert is willing to help contribute to Android apps to help integrate with our API when ready - @korfuri point of contact for Engelsystem integration - @stb worked with web sockets with Django - @oskar like to dev, moderate experience with python backends and native JS frontends Feel free to add yourself if you're interested in joining the efforts!

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully