Set labels within profile

main
bashrc 2026-08-21 20:29:05 +01:00
parent 92937bf871
commit afb8375a14
38 changed files with 242 additions and 133 deletions

View File

@ -75,7 +75,7 @@ from src.tests import test_update_actor
from src.tests import run_all_tests
from src.auth import store_basic_credentials
from src.auth import create_password
from src.utils import get_labels_from_json
from src.content_labels import get_labels_from_json
from src.utils import resembles_domain
from src.utils import string_starts_with
from src.utils import is_yggdrasil_url

View File

@ -10,7 +10,7 @@ __module_group__ = "ActivityPub"
import os
from src.content import replace_emoji_from_tags
from src.webapp_utils import labels_list_html
from src.content_labels import labels_list_html
from src.webapp_utils import html_header_with_external_style
from src.webapp_utils import html_header_with_blog_markup
from src.webapp_utils import html_footer
@ -18,7 +18,7 @@ from src.webapp_utils import get_post_attachments_as_html
from src.webapp_utils import edit_text_area
from src.webapp_media import add_embedded_elements
from src.timeFunctions import date_from_string_format
from src.utils import get_labels_from_json
from src.content_labels import get_labels_from_json
from src.utils import replace_embedded_map_with_link
from src.utils import replace_strings
from src.utils import data_dir

View File

@ -0,0 +1,147 @@
__filename__ = "content_labels.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.7.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@libreserver.org"
__status__ = "Production"
__module_group__ = "Daemon POST"
from src.utils import remove_html
from src.utils import resembles_url
from src.utils import has_object_dict
MAX_CONTENT_LABELS = 10
def get_labels_from_json(json_object: {}) -> []:
"""Returns labels attached to an actor or post
"""
tags_list: list[dict] = []
obj: dict = json_object
if has_object_dict(json_object):
obj = json_object['object']
if 'tag' in obj:
if isinstance(obj['tag'], list):
tags_list = obj['tag']
if 'attachment' in json_object:
if isinstance(json_object['attachment'], list):
tags_list = json_object['attachment']
if not tags_list:
return []
labels: list[str] = []
for tag_dict in tags_list:
if not isinstance(tag_dict, dict):
continue
if 'type' not in tag_dict or 'name' not in tag_dict:
continue
if 'value' not in tag_dict and 'href' not in tag_dict:
continue
if not isinstance(tag_dict['type'], str):
continue
if not isinstance(tag_dict['name'], str):
continue
if tag_dict['type'] == 'PropertyValue' and \
'value' in tag_dict:
if not isinstance(tag_dict['value'], str):
continue
if tag_dict['name'] == 'Labels':
if ',' in tag_dict['value']:
labels_list = tag_dict['value'].split(',')
else:
labels_list = tag_dict['value'].split('/')
for label_str in labels_list:
label_str = label_str.strip()
label_str = remove_html(label_str)
if label_str:
if len(labels) >= MAX_CONTENT_LABELS:
break
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
elif tag_dict['name'] == 'Label':
label_str = tag_dict['value'].strip()
label_str = remove_html(label_str)
if label_str:
if 'href' in tag_dict:
if isinstance(tag_dict['href'], str):
if resembles_url(tag_dict['href']):
label_str += '###' + tag_dict['href']
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
elif tag_dict['type'] == 'Label':
label_str = remove_html(tag_dict['name'])
if label_str:
if 'href' in tag_dict:
if isinstance(tag_dict['href'], str):
if resembles_url(tag_dict['href']):
label_str += '###' + tag_dict['href']
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
return labels
def labels_list_html(labels_list: []) -> str:
"""Returns html for a list of labels for an actor or post
"""
labels_str = ''
for label in labels_list:
label_url = ''
if '###' in label:
label_url = label.split('###')[1]
label = label.split('###')[0]
if labels_str:
labels_str += ' '
if not label_url:
labels_str += '<mark>' + label + '</mark>'
else:
labels_str += '<mark><a href="' + label_url + \
'" target="_blank" rel="nofollow noopener noreferrer">' + \
label + '</a></mark>'
if labels_str:
labels_str = '<p>' + labels_str + '</p>\n'
return labels_str
def get_actor_content_labels(actor_json: {}) -> str:
"""Returns a string containing comma separated content labels
from the given account actor
"""
labels_list: list[str] = get_labels_from_json(actor_json)
labels_str = ''
for lbl in labels_list:
if labels_str:
labels_str += ', '
labels_str += lbl
return labels_str
def set_actor_content_labels(actor_json: {}, labels: str) -> None:
"""Sets a string containing comma separated content labels
within the given account actor
"""
labels = remove_html(labels)
if 'attachment' not in actor_json:
actor_json['attachment'] = []
for tag_dict in actor_json['attachment']:
if 'name' not in tag_dict:
continue
if not isinstance(tag_dict['name'], str):
continue
if tag_dict['name'] == 'Labels':
tag_dict['value'] = labels
return
labels_dict = {
'type': 'PropertyValue',
'name': 'Labels',
'value': labels
}
actor_json['attachment'].append(labels_dict)

View File

@ -157,6 +157,8 @@ from src.data import erase_file
from src.data import is_a_file
from src.data import is_a_dir
from src.data import makedir
from src.content_labels import get_actor_content_labels
from src.content_labels import set_actor_content_labels
def _profile_post_deactivate_account(base_dir: str, nickname: str, domain: str,
@ -1610,6 +1612,24 @@ def _profile_post_featured_hashtags(base_dir: str, nickname: str, domain: str,
return
def _profile_post_content_labels(fields: {}, actor_json: {},
actor_changed: bool) -> bool:
""" HTTP POST content labels on edit profile screen
"""
labels_str = get_actor_content_labels(actor_json)
if fields.get('contentLabels'):
fields['contentLabels'] = remove_html(fields['contentLabels'])
if labels_str != fields['contentLabels']:
set_actor_content_labels(actor_json,
fields['contentLabels'])
actor_changed = True
else:
if labels_str:
set_actor_content_labels(actor_json, '')
actor_changed = True
return actor_changed
def _profile_post_occupation(actor_json: {}, fields: {},
actor_changed: bool) -> bool:
""" HTTP POST occupation on edit profile screen
@ -3204,6 +3224,10 @@ def profile_edit(self, calling_domain: str, cookie: str,
_profile_post_featured_hashtags(base_dir, nickname, domain,
fields)
actor_changed = \
_profile_post_content_labels(fields, actor_json,
actor_changed)
actor_changed = \
_profile_post_alsoknownas(actor_json, fields,
actor_changed)

View File

@ -28,7 +28,7 @@ from src.posts import add_to_field
from src.status import actor_status_expired
from src.status import get_actor_status
from src.mitm import detect_mitm
from src.utils import get_labels_from_json
from src.content_labels import get_labels_from_json
from src.utils import valid_nickname
from src.utils import is_yggdrasil_url
from src.utils import data_dir

View File

@ -59,8 +59,6 @@ INVALID_ACTOR_URL_CHARACTERS = (
';', '='
)
MAX_CONTENT_LABELS = 10
def is_account_dir(dir_name: str) -> bool:
"""Is the given directory an account within /accounts ?
@ -4456,75 +4454,3 @@ def url_text_to_number(url: str) -> str:
"""
hash_result = get_sha_256(url)
return base64.b64encode(hash_result).decode('utf-8')
def get_labels_from_json(json_object: {}) -> []:
"""Returns labels attached to an actor or post
"""
tags_list: list[dict] = []
obj: dict = json_object
if has_object_dict(json_object):
obj = json_object['object']
if 'tag' in obj:
if isinstance(obj['tag'], list):
tags_list = obj['tag']
if 'attachment' in json_object:
if isinstance(json_object['attachment'], list):
tags_list = json_object['attachment']
if not tags_list:
return []
labels: list[str] = []
for tag_dict in tags_list:
if not isinstance(tag_dict, dict):
continue
if 'type' not in tag_dict or 'name' not in tag_dict:
continue
if 'value' not in tag_dict and 'href' not in tag_dict:
continue
if not isinstance(tag_dict['type'], str):
continue
if not isinstance(tag_dict['name'], str):
continue
if tag_dict['type'] == 'PropertyValue' and \
'value' in tag_dict:
if not isinstance(tag_dict['value'], str):
continue
if tag_dict['name'] == 'Labels':
if ',' in tag_dict['value']:
labels_list = tag_dict['value'].split(',')
else:
labels_list = tag_dict['value'].split('/')
for label_str in labels_list:
label_str = label_str.strip()
label_str = remove_html(label_str)
if label_str:
if len(labels) >= MAX_CONTENT_LABELS:
break
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
elif tag_dict['name'] == 'Label':
label_str = tag_dict['value'].strip()
label_str = remove_html(label_str)
if label_str:
if 'href' in tag_dict:
if isinstance(tag_dict['href'], str):
if resembles_url(tag_dict['href']):
label_str += '###' + tag_dict['href']
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
elif tag_dict['type'] == 'Label':
label_str = remove_html(tag_dict['name'])
if label_str:
if 'href' in tag_dict:
if isinstance(tag_dict['href'], str):
if resembles_url(tag_dict['href']):
label_str += '###' + tag_dict['href']
labels.append(label_str)
# limit the number of labels
if len(labels) >= MAX_CONTENT_LABELS:
break
return labels

View File

@ -30,7 +30,7 @@ from src.follow import is_following_actor
from src.followingCalendar import receiving_calendar_events
from src.notifyOnPost import notify_when_person_posts
from src.person import get_person_notes
from src.webapp_utils import labels_list_html
from src.content_labels import labels_list_html
from src.webapp_utils import mitm_warning_html
from src.webapp_utils import html_header_with_external_style
from src.webapp_utils import html_footer

View File

@ -42,7 +42,7 @@ from src.textmode import text_mode_removals
from src.quote import get_quote_toot_url
from src.timeFunctions import date_from_string_format
from src.timeFunctions import convert_published_to_local_timezone
from src.utils import get_labels_from_json
from src.content_labels import get_labels_from_json
from src.utils import is_private_browser
from src.utils import replace_embedded_map_with_link
from src.utils import get_mutuals_of_person
@ -109,7 +109,7 @@ from src.content import add_auto_cw
from src.person import is_person_snoozed
from src.person import get_person_avatar_url
from src.textmode import text_mode_browser
from src.webapp_utils import labels_list_html
from src.content_labels import labels_list_html
from src.webapp_utils import get_display_name_prefix
from src.webapp_utils import get_show_map_button
from src.webapp_utils import mitm_warning_html

View File

@ -22,7 +22,7 @@ from src.textmode import text_mode_removals
from src.unicodetext import uninvert_text
from src.unicodetext import standardize_text
from src.occupation import get_occupation_name
from src.utils import get_labels_from_json
from src.content_labels import get_labels_from_json
from src.utils import get_preferred_username
from src.utils import is_private_browser
from src.utils import replace_embedded_map_with_link
@ -104,7 +104,7 @@ from src.follow import get_follower_domains
from src.follow import is_following_actor
from src.webapp_frontscreen import html_front_screen
from src.textmode import text_mode_browser
from src.webapp_utils import labels_list_html
from src.content_labels import labels_list_html
from src.webapp_utils import get_display_name_prefix
from src.webapp_utils import html_following_dropdown
from src.webapp_utils import edit_number_field
@ -3560,6 +3560,12 @@ def _html_edit_profile_main(base_dir: str, display_nickname: str,
edit_text_field(translate['Featured hashtags'], 'featuredHashtags',
featured_hashtags, '#tag1 #tag2')
labels_list: list[str] = get_labels_from_json(actor_json)
labels_str = labels_list_html(labels_list)
edit_profile_form += \
edit_text_field(translate['Content labels'], 'contentLabels',
labels_str, '1, 2, 3...')
edit_profile_form += \
' <label class="labels">' + translate['Avatar image'] + \
'</label>\n' + \

View File

@ -2567,25 +2567,3 @@ def get_display_name_prefix(actor_type: str,
nickname in chatbot_nicknames()):
display_name_prefix = '<b>[' + translate['Bot'] + ']</b> '
return display_name_prefix
def labels_list_html(labels_list: []) -> str:
"""Returns html for a list of labels for an actor or post
"""
labels_str = ''
for label in labels_list:
label_url = ''
if '###' in label:
label_url = label.split('###')[1]
label = label.split('###')[0]
if labels_str:
labels_str += ' '
if not label_url:
labels_str += '<mark>' + label + '</mark>'
else:
labels_str += '<mark><a href="' + label_url + \
'" target="_blank" rel="nofollow noopener noreferrer">' + \
label + '</a></mark>'
if labels_str:
labels_str = '<p>' + labels_str + '</p>\n'
return labels_str

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "أمثلة على التضليل الإعلامي",
"Allow this account to be added to lists": "السماح بإضافة هذا الحساب إلى القوائم",
"Apply dithering to images.": "طبّق تقنية التدرج النقطي (dithering) على الصور.",
"Replace dashes with em dashes": "استبدل الشرطات (-) بشرطات طويلة (—)"
"Replace dashes with em dashes": "استبدل الشرطات (-) بشرطات طويلة (—)",
"Content labels": "تصنيفات المحتوى"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "ভুল তথ্যের উদাহরণ",
"Allow this account to be added to lists": "এই অ্যাকাউন্টটিকে তালিকায় যুক্ত করার অনুমতি দিন",
"Apply dithering to images.": "ছবিতে ডিদারিং প্রয়োগ করুন।",
"Replace dashes with em dashes": "ড্যাশগুলোকে এম-ড্যাশ (em dashes) দিয়ে প্রতিস্থাপন করুন।"
"Replace dashes with em dashes": "ড্যাশগুলোকে এম-ড্যাশ (em dashes) দিয়ে প্রতিস্থাপন করুন।",
"Content labels": "বিষয়বস্তুর লেবেল"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Instàncies de desinformació",
"Allow this account to be added to lists": "Permet que aquest compte s'afegeixi a les llistes",
"Apply dithering to images.": "Aplica el dithering a les imatges.",
"Replace dashes with em dashes": "Substitueix els guions per guions circulars"
"Replace dashes with em dashes": "Substitueix els guions per guions circulars",
"Content labels": "Etiquetes de contingut"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Achosion o Ddadwybodaeth",
"Allow this account to be added to lists": "Caniatáu i'r cyfrif hwn gael ei ychwanegu at restrau",
"Apply dithering to images.": "Cymhwyso dithering i ddelweddau.",
"Replace dashes with em dashes": "Disodli llinellau byr gyda llinellau byr em"
"Replace dashes with em dashes": "Disodli llinellau byr gyda llinellau byr em",
"Content labels": "Labeli cynnwys"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Fälle von Desinformation",
"Allow this account to be added to lists": "Erlauben, dass dieses Konto zu Listen hinzugefügt wird",
"Apply dithering to images.": "Wenden Sie Dithering auf Bilder an.",
"Replace dashes with em dashes": "Ersetzen Sie Bindestriche durch Geviertstriche."
"Replace dashes with em dashes": "Ersetzen Sie Bindestriche durch Geviertstriche.",
"Content labels": "Inhaltsbezeichnungen"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Περιπτώσεις παραπληροφόρησης",
"Allow this account to be added to lists": "Να επιτρέπεται η προσθήκη αυτού του λογαριασμού σε λίστες",
"Apply dithering to images.": "Εφαρμογή πρόσμειξης σε εικόνες.",
"Replace dashes with em dashes": "Αντικαταστήστε τις παύλες με παύλες em"
"Replace dashes with em dashes": "Αντικαταστήστε τις παύλες με παύλες em",
"Content labels": "Ετικέτες περιεχομένου"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Disinformation Instances",
"Allow this account to be added to lists": "Allow this account to be added to lists",
"Apply dithering to images.": "Apply dithering to images.",
"Replace dashes with em dashes": "Replace dashes with em dashes"
"Replace dashes with em dashes": "Replace dashes with em dashes",
"Content labels": "Content labels"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Casos de desinformación",
"Allow this account to be added to lists": "Permitir que esta cuenta se añada a listas",
"Apply dithering to images.": "Aplica tramado a las imágenes.",
"Replace dashes with em dashes": "Reemplaza los guiones por rayas."
"Replace dashes with em dashes": "Reemplaza los guiones por rayas.",
"Content labels": "Etiquetas de contenido"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "موارد انتشار اطلاعات نادرست",
"Allow this account to be added to lists": "اجازه دهید این حساب به لیست‌ها اضافه شود",
"Apply dithering to images.": "اعمال لرزش (dithering) روی تصاویر",
"Replace dashes with em dashes": "خط تیره را با خط تیره em جایگزین کنید"
"Replace dashes with em dashes": "خط تیره را با خط تیره em جایگزین کنید",
"Content labels": "برچسب‌های محتوا"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Disinformaatiotapaukset",
"Allow this account to be added to lists": "Salli tämän tilin lisääminen listoihin",
"Apply dithering to images.": "Käytä kuviin rasterointia.",
"Replace dashes with em dashes": "Korvaa viivat em-viivoilla"
"Replace dashes with em dashes": "Korvaa viivat em-viivoilla",
"Content labels": "Sisältötunnisteet"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Cas de désinformation",
"Allow this account to be added to lists": "Autoriser l'ajout de ce compte à des listes",
"Apply dithering to images.": "Appliquez le tramage aux images.",
"Replace dashes with em dashes": "Remplacez les tirets par des tirets cadratins."
"Replace dashes with em dashes": "Remplacez les tirets par des tirets cadratins.",
"Content labels": "Étiquettes de contenu"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Cásanna Mífhaisnéise",
"Allow this account to be added to lists": "Ceadaigh an cuntas seo a chur le liostaí",
"Apply dithering to images.": "Cuir díodrú i bhfeidhm ar íomhánna.",
"Replace dashes with em dashes": "Cuir fleascáin em in ionad fleascáin"
"Replace dashes with em dashes": "Cuir fleascáin em in ionad fleascáin",
"Content labels": "Lipéid ábhair"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "מקרים של דיסאינפורמציה",
"Allow this account to be added to lists": "אפשר הוספת חשבון זה לרשימות",
"Apply dithering to images.": "החלת דיטרינג על תמונות.",
"Replace dashes with em dashes": "החלפת מקפים במקפים em"
"Replace dashes with em dashes": "החלפת מקפים במקפים em",
"Content labels": "תוויות תוכן"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "गलत सूचना के उदाहरण",
"Allow this account to be added to lists": "इस अकाउंट को लिस्ट में जोड़ने की अनुमति दें",
"Apply dithering to images.": "इमेज पर डिथरिंग लागू करें।",
"Replace dashes with em dashes": "डैश की जगह एम-डैश (em dashes) का इस्तेमाल करें।"
"Replace dashes with em dashes": "डैश की जगह एम-डैश (em dashes) का इस्तेमाल करें।",
"Content labels": "कंटेंट लेबल"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Esempi di disinformazione",
"Allow this account to be added to lists": "Consenti l'aggiunta di questo account agli elenchi",
"Apply dithering to images.": "Applica il dithering alle immagini.",
"Replace dashes with em dashes": "Sostituisci i trattini con i trattini lunghi."
"Replace dashes with em dashes": "Sostituisci i trattini con i trattini lunghi.",
"Content labels": "Etichette dei contenuti"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "偽情報事例",
"Allow this account to be added to lists": "このアカウントをリストに追加できるようにする",
"Apply dithering to images.": "画像にディザリングを適用します。",
"Replace dashes with em dashes": "ダッシュをemダッシュに置き換えてください"
"Replace dashes with em dashes": "ダッシュをemダッシュに置き換えてください",
"Content labels": "コンテンツラベル"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "허위 정보 사례",
"Allow this account to be added to lists": "이 계정을 목록에 추가할 수 있도록 허용",
"Apply dithering to images.": "이미지에 디더링을 적용합니다.",
"Replace dashes with em dashes": "대시를 엠 대시로 바꾸세요."
"Replace dashes with em dashes": "대시를 엠 대시로 바꾸세요.",
"Content labels": "콘텐츠 라벨"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Nimûneyên Dezînformasyonê",
"Allow this account to be added to lists": "Destûrê bide ku ev hesab li navnîşan were zêdekirin",
"Apply dithering to images.": "Ditheringê li ser wêneyan bicîh bîne.",
"Replace dashes with em dashes": "Xêzên xêzkirî bi xêzên em biguherînin"
"Replace dashes with em dashes": "Xêzên xêzkirî bi xêzên em biguherînin",
"Content labels": "Etîketên naverokê"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Voorbeelden van desinformatie",
"Allow this account to be added to lists": "Toestaan dat dit account aan lijsten wordt toegevoegd",
"Apply dithering to images.": "Pas dithering toe op afbeeldingen.",
"Replace dashes with em dashes": "Vervang koppeltekens door kastlijntjes."
"Replace dashes with em dashes": "Vervang koppeltekens door kastlijntjes.",
"Content labels": "Inhoudslabels"
}

View File

@ -770,5 +770,6 @@
"Disinformation Instances": "Instàncias de desinformacion",
"Allow this account to be added to lists": "Autorizar aqueste compte a èsser apondut a las listas",
"Apply dithering to images.": "Aplicar lo tremolament a d'imatges.",
"Replace dashes with em dashes": "Remplaçatz los tirets per de tirets em"
"Replace dashes with em dashes": "Remplaçatz los tirets per de tirets em",
"Content labels": "Etiquetas de contengut"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Przypadki dezinformacji",
"Allow this account to be added to lists": "Zezwól na dodawanie tego konta do list",
"Apply dithering to images.": "Zastosuj dithering do obrazów.",
"Replace dashes with em dashes": "Zastąp myślniki pauzami."
"Replace dashes with em dashes": "Zastąp myślniki pauzami.",
"Content labels": "Etykiety zawartości"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Casos de desinformação",
"Allow this account to be added to lists": "Permitir que esta conta seja adicionada às listas",
"Apply dithering to images.": "Aplicar dithering às imagens.",
"Replace dashes with em dashes": "Substitua os travessões por travessões longos."
"Replace dashes with em dashes": "Substitua os travessões por travessões longos.",
"Content labels": "Rótulos de conteúdo"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Случаи дезинформации",
"Allow this account to be added to lists": "Разрешить добавление этого аккаунта в списки",
"Apply dithering to images.": "Примените дизеринг к изображениям.",
"Replace dashes with em dashes": "Замените дефисы на тире."
"Replace dashes with em dashes": "Замените дефисы на тире.",
"Content labels": "Метки контента"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Matukio ya Taarifa Potofu",
"Allow this account to be added to lists": "Ruhusu akaunti hii iongezwe kwenye orodha",
"Apply dithering to images.": "Weka upau wa kuchorea kwenye picha.",
"Replace dashes with em dashes": "Badilisha dashibodi na dashibodi za em"
"Replace dashes with em dashes": "Badilisha dashibodi na dashibodi za em",
"Content labels": "Lebo za maudhui"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Dezenformasyon Vakaları",
"Allow this account to be added to lists": "Bu hesabın listelere eklenmesine izin ver",
"Apply dithering to images.": "Görüntülere dithering uygulayın.",
"Replace dashes with em dashes": "Kısa çizgileri uzun çizgilerle (em dash) değiştirin."
"Replace dashes with em dashes": "Kısa çizgileri uzun çizgilerle (em dash) değiştirin.",
"Content labels": "İçerik etiketleri"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "Випадки дезінформації",
"Allow this account to be added to lists": "Дозволити додавання цього облікового запису до списків",
"Apply dithering to images.": "Застосуйте дизеринг до зображень.",
"Replace dashes with em dashes": "Замініть тире довгими тире"
"Replace dashes with em dashes": "Замініть тире довгими тире",
"Content labels": "Мітки контенту"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "דיסאינפארמאציע אינסטאַנצן",
"Allow this account to be added to lists": "ערלויבן דעם חשבון צו ווערן צוגעגעבן צו ליסטעס",
"Apply dithering to images.": "צולייגן דיטערינג צו בילדער.",
"Replace dashes with em dashes": "פֿאַרבײַטן די שטריכלעך מיט עמ־שטרייכלעך"
"Replace dashes with em dashes": "פֿאַרבײַטן די שטריכלעך מיט עמ־שטרייכלעך",
"Content labels": "אינהאַלט עטיקעטן"
}

View File

@ -774,5 +774,6 @@
"Disinformation Instances": "虚假信息实例",
"Allow this account to be added to lists": "允许将此帐户添加到列表中",
"Apply dithering to images.": "对图像应用抖动处理。",
"Replace dashes with em dashes": "将连字符替换为长破折号"
"Replace dashes with em dashes": "将连字符替换为长破折号",
"Content labels": "内容标签"
}