@jjlmoya/utils-streaming 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/src/category/i18n/de.ts +134 -0
- package/src/category/i18n/id.ts +134 -0
- package/src/category/i18n/it.ts +134 -0
- package/src/category/i18n/ja.ts +134 -0
- package/src/category/i18n/ko.ts +134 -0
- package/src/category/i18n/nl.ts +134 -0
- package/src/category/i18n/pl.ts +134 -0
- package/src/category/i18n/pt.ts +134 -0
- package/src/category/i18n/ru.ts +134 -0
- package/src/category/i18n/sv.ts +134 -0
- package/src/category/i18n/tr.ts +134 -0
- package/src/category/i18n/zh.ts +134 -0
- package/src/category/index.ts +12 -0
- package/src/tests/i18n_coverage.test.ts +36 -0
- package/src/tests/locale_completeness.test.ts +1 -1
- package/src/tests/slug_uniqueness.test.ts +81 -0
- package/src/tool/sorteo/component.astro +5 -7
- package/src/tool/sorteo/i18n/de.ts +256 -0
- package/src/tool/sorteo/i18n/en.ts +3 -0
- package/src/tool/sorteo/i18n/es.ts +3 -0
- package/src/tool/sorteo/i18n/fr.ts +3 -0
- package/src/tool/sorteo/i18n/id.ts +256 -0
- package/src/tool/sorteo/i18n/it.ts +256 -0
- package/src/tool/sorteo/i18n/ja.ts +256 -0
- package/src/tool/sorteo/i18n/ko.ts +256 -0
- package/src/tool/sorteo/i18n/nl.ts +256 -0
- package/src/tool/sorteo/i18n/pl.ts +256 -0
- package/src/tool/sorteo/i18n/pt.ts +256 -0
- package/src/tool/sorteo/i18n/ru.ts +256 -0
- package/src/tool/sorteo/i18n/sv.ts +256 -0
- package/src/tool/sorteo/i18n/tr.ts +256 -0
- package/src/tool/sorteo/i18n/zh.ts +256 -0
- package/src/tool/sorteo/index.ts +12 -0
- package/src/tool/sorteo/ui.ts +3 -0
- package/src/tool/tebasCheck/component.astro +4 -6
- package/src/tool/tebasCheck/i18n/de.ts +256 -0
- package/src/tool/tebasCheck/i18n/en.ts +2 -0
- package/src/tool/tebasCheck/i18n/es.ts +2 -0
- package/src/tool/tebasCheck/i18n/fr.ts +2 -0
- package/src/tool/tebasCheck/i18n/id.ts +256 -0
- package/src/tool/tebasCheck/i18n/it.ts +256 -0
- package/src/tool/tebasCheck/i18n/ja.ts +256 -0
- package/src/tool/tebasCheck/i18n/ko.ts +256 -0
- package/src/tool/tebasCheck/i18n/nl.ts +256 -0
- package/src/tool/tebasCheck/i18n/pl.ts +256 -0
- package/src/tool/tebasCheck/i18n/pt.ts +256 -0
- package/src/tool/tebasCheck/i18n/ru.ts +256 -0
- package/src/tool/tebasCheck/i18n/sv.ts +256 -0
- package/src/tool/tebasCheck/i18n/tr.ts +256 -0
- package/src/tool/tebasCheck/i18n/zh.ts +256 -0
- package/src/tool/tebasCheck/index.ts +12 -0
- package/src/tool/tebasCheck/types.ts +3 -1
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SorteoUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'rastgele-isim-secici';
|
|
6
|
+
const title = 'Streaming için Rastgele İsim Seçici';
|
|
7
|
+
const description =
|
|
8
|
+
'İsim listesinden rastgele bir kazanan seçin. Twitch, YouTube ve etkinlikler için ücretsiz, hızlı ve görsel çekiliş aracı.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Bu çekiliş gerçekten rastgele mi?',
|
|
13
|
+
answer:
|
|
14
|
+
'Evet, her katılımcının herhangi bir önyargı veya manipülasyon olmaksızın tam olarak aynı kazanma olasılığına sahip olmasını sağlamak için tarayıcının kriptografik rastgelelik algoritmasını (Web Crypto API) kullanıyoruz.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Bu çekiliş aracını Twitch veya YouTube\'da kullanabilir miyim?',
|
|
18
|
+
answer:
|
|
19
|
+
'Kesinlikle. Bir web aracı olarak, pencereyi OBS ile yakalayabilir veya ekranınızı doğrudan paylaşabilirsiniz. Temiz tasarımı ve animasyonları, izleyicilerin süreci tam bir şeffaflıkla görebilmesi için tasarlanmıştır.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Bir kişinin iki kez katılmasını nasıl önlerim?',
|
|
23
|
+
answer:
|
|
24
|
+
'Araç, her gerçek kişinin yalnızca bir kez sayılmasını sağlamak için aynı isimleri veya küçük boşluk varyasyonlarına sahip isimleri tespit eden otomatik bir "mükerrer temizleme" işlevine sahiptir.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'Aynı anda birkaç kazanan çekebilir miyim?',
|
|
28
|
+
answer:
|
|
29
|
+
'Evet, düğmeye tıklamadan önce istediğiniz kazanan sayısını yapılandırabilirsiniz. Araç, şanslı kişileri canlı yayınınızda belirtebilmeniz için net bir şekilde listeleyecektir.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: 'Listeye kaç isim ekleyebilirim?',
|
|
33
|
+
answer:
|
|
34
|
+
'Araç tarafından uygulanan katı bir sınır yoktur. Motoru, binlerce katılımcıdan oluşan listeleri performans sorunu olmadan işleyecek şekilde optimize ettik; bu da onu kitlesel çekilişler için bile ideal kılar.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: 'Verilerim veya katılımcı listesi kaydediliyor mu?',
|
|
38
|
+
answer:
|
|
39
|
+
'Hayır, asla. Gizliliğiniz her şeyden önce gelir. Tüm çekiliş süreci web tarayıcınızda yerel olarak çalışır. Girdiğiniz isimler asla sunucularımıza gönderilmez veya herhangi bir veritabanında saklanmaz.',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const howToData = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Katılımcı listesini hazırlayın',
|
|
46
|
+
text: 'Sohbetenizden, Excel\'den veya sosyal ağdan isim listesini kopyalayın ve metin kutusuna yapıştırın.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Çekiliş seçeneklerini yapılandırın',
|
|
50
|
+
text: 'Kaç kazanana ihtiyacınız olduğunu ve mükerrerleri veya boş isimleri filtrelemek isteyip istemediğinizi seçin.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Çekilişi başlatın',
|
|
54
|
+
text: 'Çekiliş düğmesine tıklayın. Görsel bir animasyon, kazanan açıklanmadan önce heyecanı koruyacaktır.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Sonuçları duyurun',
|
|
58
|
+
text: 'Kazananların isimlerini sosyal ağlarınızda veya yayın sohbetinizde paylaşmak için kopyalayın.',
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
63
|
+
'@context': 'https://schema.org',
|
|
64
|
+
'@type': 'FAQPage',
|
|
65
|
+
mainEntity: faqData.map((item) => ({
|
|
66
|
+
'@type': 'Question',
|
|
67
|
+
name: item.question,
|
|
68
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
69
|
+
})),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const howToSchema: WithContext<HowTo> = {
|
|
73
|
+
'@context': 'https://schema.org',
|
|
74
|
+
'@type': 'HowTo',
|
|
75
|
+
name: title,
|
|
76
|
+
description,
|
|
77
|
+
step: howToData.map((step, i) => ({
|
|
78
|
+
'@type': 'HowToStep',
|
|
79
|
+
position: i + 1,
|
|
80
|
+
name: step.name,
|
|
81
|
+
text: step.text,
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
86
|
+
'@context': 'https://schema.org',
|
|
87
|
+
'@type': 'SoftwareApplication',
|
|
88
|
+
name: title,
|
|
89
|
+
description,
|
|
90
|
+
applicationCategory: 'UtilityApplication',
|
|
91
|
+
operatingSystem: 'All',
|
|
92
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
93
|
+
inLanguage: 'tr',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const content: ToolLocaleContent<SorteoUI> = {
|
|
97
|
+
slug,
|
|
98
|
+
title,
|
|
99
|
+
description,
|
|
100
|
+
faqTitle: 'Sıkça Sorulan Sorular',
|
|
101
|
+
faq: faqData,
|
|
102
|
+
bibliographyTitle: 'Teknik Referanslar',
|
|
103
|
+
bibliography: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Web Crypto API: getRandomValues()',
|
|
106
|
+
url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Fisher-Yates Karıştırma Algoritması',
|
|
110
|
+
url: 'https://tr.wikipedia.org/wiki/Fisher-Yates_kar%C4%B1%C5%9Ft%C4%B1rma_algoritmas%C4%B1',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
howTo: howToData,
|
|
114
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema as any],
|
|
115
|
+
seo: [
|
|
116
|
+
{
|
|
117
|
+
type: 'title',
|
|
118
|
+
text: 'Online Rastgele İsim Seçici ve Katılımcı Listesi',
|
|
119
|
+
level: 2,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: 'paragraph',
|
|
123
|
+
html: 'Online bir çekilişi hızlı, güvenli ve tamamen şeffaf bir şekilde nasıl yapacağınızı mı merak ediyorsunuz? Ücretsiz <strong>İsim Seçici</strong> aracımız, saniyeler içinde rastgele bir kazanan seçmek için mükemmel bir çözümdür. Basit, görsel ve etkili olacak şekilde tasarlanmıştır; dijital bir "adil seçime" ihtiyaç duyduğunuz her durum için idealdir.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'paragraph',
|
|
127
|
+
html: 'İster sosyal ağlarda bir yarışma yönetiyor olun, ister yayın kanalınızda kitlesel bir çekiliş yapın, ister sadece bugün çöpü kimin çıkaracağına karar verin, rastgele seçicimiz modern kriptografik algoritmalar sayesinde tam tarafsızlığı garanti eder. <strong>Manipülasyon yok, taraf tutma yok, sadece saf rastgelelik.</strong>'
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'title',
|
|
131
|
+
text: 'Kullanım Örnekleri',
|
|
132
|
+
level: 3,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'comparative',
|
|
136
|
+
columns: 2,
|
|
137
|
+
items: [
|
|
138
|
+
{
|
|
139
|
+
title: 'Sosyal Medya Çekilişleri',
|
|
140
|
+
description: 'Instagram, Twitter (X) veya Facebook yarışmaları için idealdir. Sadece yorumlardan isimleri kopyalayın ve adil bir kazanan seçmek için yapıştırın. Araç mükerrerleri otomatik olarak kaldırır.',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
title: 'Twitch / YouTube Yayını',
|
|
144
|
+
description: 'Pürüzsüz animasyonlar ve entegre seslere sahip Stüdyo Modumuz sayesinde ekranınızı doğrudan OBS\'de paylaşabilir ve canlı kazananları seçerken izleyicilerinize heyecan verici bir görsel şov sunabilirsiniz.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
title: 'Sınıf ve Takım Dinamikleri',
|
|
148
|
+
description: 'Öğretmenler ve takım liderleri, rastgele gruplar oluşturmak, ilk kimin sunum yapacağını seçmek veya tam şeffaflıkla ve kayırmacılık yapmadan görevleri rastgele atamak için kullanabilirler.',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
title: 'Noel Baba Çekilişi ve Etkinlikler',
|
|
152
|
+
description: 'Kağıtlara veya karmaşık lojistiklere ihtiyaç duymadan anında rastgele isim seçerek aile etkinliklerinin, ofis çekilişlerinin veya Noel Baba çekilişlerinin organizasyonunu basitleştirin.',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
type: 'title',
|
|
158
|
+
text: 'Aracımız Neden Farklı?',
|
|
159
|
+
level: 3,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: 'list',
|
|
163
|
+
items: [
|
|
164
|
+
'<strong>Gerçek Kriptografi:</strong> Zayıf sözde rastgele üreteçler yerine tarayıcının Web Crypto API\'sini (W3C standardı) kullanıyoruz. Her çekiliş matematiksel olarak tarafsızdır.',
|
|
165
|
+
'<strong>Depolama Yok:</strong> Verileriniz asla tarayıcınızdan çıkmaz. Liste satmıyoruz, profilinizi çıkarmıyoruz, hiçbir şeyi saklamıyoruz. Tamamen yerel işleme.',
|
|
166
|
+
'<strong>Görsel Tasarım:</strong> Sinema modu ve animasyonlar her çekilişi unutulmaz bir etkinlik haline getirir. OBS yakalama veya canlı yayın için mükemmeldir.',
|
|
167
|
+
'<strong>Mükerrer Yönetimi:</strong> Her gerçek kişinin yalnızca bir kez sayılmasını sağlamak için yinelenen isimleri veya varyasyonları (ekstra boşluklar, büyük/küçük harf vb.) otomatik olarak tespit eder.',
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: 'title',
|
|
172
|
+
text: 'Adım Adım Çekiliş Nasıl Kullanılır?',
|
|
173
|
+
level: 3,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'list',
|
|
177
|
+
items: [
|
|
178
|
+
'<strong>Adım 1 - Katılımcıları girin:</strong> İsim listenizi ana metin kutusuna yapıştırın. Araç, her satır sonunu otomatik olarak farklı bir katılımcı olarak algılar. Mükerrer mi var? Sorun değil, araç onları kaldırır.',
|
|
179
|
+
'<strong>Adım 2 - Özelleştirin:</strong> Ayarlar sekmesinde heyecan yaratmak için geri sayımı, kutlamak için konfeti efektini etkinleştirebilir veya belirli isimleri hariç tutmak için "kara listeyi" etkinleştirebilirsiniz.',
|
|
180
|
+
'<strong>Adım 3 - Çekilişi başlatın!</strong> Ana düğmeye tıklayın ve motorumuz kriptografik olarak güvenli rastgele bir seçim oluşturacaktır. Kazananlar net ve akılda kalıcı bir şekilde görüntülenecektir.',
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: 'title',
|
|
185
|
+
text: 'Ağırlıklı Girişler: Bazı Katılımcılara Avantaj Sağlayın',
|
|
186
|
+
level: 3,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'paragraph',
|
|
190
|
+
html: 'En sadık abonelerinizi ödüllendirmek veya belirli katılımcılara daha fazla fırsat mı vermek istiyorsunuz? <strong>Ağırlıklı Girişler</strong> sistemimiz benzersizdir ve herhangi bir isme, onu birden çok kez yazmak zorunda kalmadan bir "ağırlık" veya çarpan atamanıza olanak tanır.',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
type: 'tip',
|
|
194
|
+
title: 'İsimlere ağırlık nasıl atanır?',
|
|
195
|
+
html: '<p>Yıldız simgesi (*) veya "x" ve ardından katılım sayısını kullanın. Örnekler:</p><ul><li><strong>"Can * 5"</strong> - Can sanki 5 kişiymiş gibi yarışır</li><li><strong>"Ayşe x 10"</strong> - Ayşe\'nin 10 kat daha fazla şansı olur</li><li><strong>"Ali"</strong> - Sembol yok = 1 normal giriş</li></ul><p>Bu, VIP abonelere veya özel kullanıcılara avantaj sağlamak istediğiniz çekilişler için mükemmeldir.</p>',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'title',
|
|
199
|
+
text: 'Tam Gizlilik ve Güvenlik',
|
|
200
|
+
level: 3,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: 'paragraph',
|
|
204
|
+
html: 'Diğer çevrimiçi araçların aksine, <strong>verilerinizi saklamıyoruz</strong>. İsimlerin tüm işlemleri ve çekilişin yürütülmesi yerel olarak kendi tarayıcınızda gerçekleşir. Katılımcı listeleriniz asla ağ üzerinden iletilmez veya herhangi bir harici sunucuda saklanmaz.',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
type: 'paragraph',
|
|
208
|
+
html: '<strong>Bu ne anlama geliyor?</strong> Katılımcı listeniz sizindir ve sadece sizedir. Sekmeyi kapattığınızda veriler kaybolur. Takip çerezleri yok, kullanıcı profilleri yok, merkezi veritabanı yok. Siz ve çekilişlerinize katılanlar için maksimum gizlilik garantisi.',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: 'title',
|
|
212
|
+
text: 'Matematiksel Şeffaflık',
|
|
213
|
+
level: 3,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: 'paragraph',
|
|
217
|
+
html: 'Bazıları şunu merak edebilir: "Ya sonuçları manipüle ederseniz?" Cevap basit: <strong>yapamayız</strong>. Çekiliş kodu deterministik ve kriptografiktir. Gizli değişkenler yok, sahne arkası oyunlar yok.',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'paragraph',
|
|
221
|
+
html: 'Her kazanan, gerçek kriptografik entropi kullanılarak listenize uygulanan Fisher-Yates Karıştırma algoritmasının doğrudan sonucudur. Süreci denetlemek isterseniz, kod kamuya açık inceleme için GitHub\'da mevcuttur.',
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
ui: {
|
|
225
|
+
faqTitle: 'Sıkça Sorulan Sorular',
|
|
226
|
+
bibliographyTitle: 'Teknik Referanslar',
|
|
227
|
+
title: 'Rastgele Çekiliş',
|
|
228
|
+
totalParticipants: 'Toplam Benzersiz Katılımcı',
|
|
229
|
+
ready: 'HAZIR',
|
|
230
|
+
participants: 'Katılımcılar',
|
|
231
|
+
settings: 'Ayarlar',
|
|
232
|
+
importFile: 'Dosya İçe Aktar',
|
|
233
|
+
clearAll: 'Tümünü temizle',
|
|
234
|
+
placeholder: 'İsimleri buraya yazın veya yapıştırın...\nAhmet Yılmaz\nAyşe Kaya\n@twitch_kullanicisi',
|
|
235
|
+
onePerLine: 'Her satıra 1 katılımcı',
|
|
236
|
+
lines: 'satır',
|
|
237
|
+
filters: 'Filtreler',
|
|
238
|
+
allowDuplicates: 'Mükerrerlere İzin Ver',
|
|
239
|
+
winnerCount: 'Kazanan Sayısı',
|
|
240
|
+
autoRemove: 'Kazananı Otomatik Kaldır',
|
|
241
|
+
blacklist: 'Kara Liste (Hariç Tut)',
|
|
242
|
+
blacklistPlaceholder: 'Yasaklı isimler (her satıra bir tane)...',
|
|
243
|
+
blacklistInfo: 'Bu kullanıcılar çekilişe girmeyecektir.',
|
|
244
|
+
sceneEffects: 'Sahne Efektleri',
|
|
245
|
+
countdown: 'Geri Sayım (3s)',
|
|
246
|
+
confetti: 'Zafer Konfetisi',
|
|
247
|
+
zenMode: 'Zen Modu (Paneli Gizle)',
|
|
248
|
+
waitingParticipants: 'Katılımcılar bekleniyor...',
|
|
249
|
+
winner: 'KAZANAN',
|
|
250
|
+
reroll: 'Yeniden Çek',
|
|
251
|
+
history: 'Bu oturumun geçmişi',
|
|
252
|
+
noWinnersYet: 'Henüz kazanan yok...',
|
|
253
|
+
startGiveaway: 'Çekilişi Başlat',
|
|
254
|
+
studioHeader: 'LIVE STUDIO v2.0',
|
|
255
|
+
},
|
|
256
|
+
};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SorteoUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'giveaway';
|
|
6
|
+
const title = '直播专用随机名字抽取器';
|
|
7
|
+
const description =
|
|
8
|
+
'从名字列表中随机抽取一名获胜者。适用于 Twitch、YouTube 和各类活动的免费、快速且具有视觉效果的抽奖工具。';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: '这个抽奖真的是随机的吗?',
|
|
13
|
+
answer:
|
|
14
|
+
'是的,我们使用浏览器的加密随机算法 (Web Crypto API) 来确保每位参与者都有完全相同的获胜概率,不存在任何偏见或操控。',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: '我可以在 Twitch 或 YouTube 上使用这个抽取器吗?',
|
|
18
|
+
answer:
|
|
19
|
+
'当然可以。作为一个网页工具,您可以通过 OBS 捕获窗口或直接共享屏幕。简洁的设计和动画旨在让观众能以完全透明的方式看到整个过程。',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: '如何防止有人重复参与?',
|
|
23
|
+
answer:
|
|
24
|
+
'该工具具有自动“去重”功能,可以检测完全相同的名字或带有微小空格差异的名字,以确保每个真实的人只被计算一次。',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: '我可以一次抽取多名获胜者吗?',
|
|
28
|
+
answer:
|
|
29
|
+
'可以,您可以在点击按钮之前配置所需的获胜者人数。工具会清晰地列出幸运儿,以便您在直播中宣布。',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: '我可以在列表中添加多少个名字?',
|
|
33
|
+
answer:
|
|
34
|
+
'工具本身没有严格的人数限制。我们已经优化了引擎,可以毫无压力地处理包含数千名参与者的列表,非常适合大规模抽奖。',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: '我的数据或参与者列表会被保存吗?',
|
|
38
|
+
answer:
|
|
39
|
+
'不,永远不会。您的隐私是我们的首要任务。整个抽奖过程在您的网页浏览器本地运行。您输入的名字永远不会发送到我们的服务器,也不会存储在任何数据库中。',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const howToData = [
|
|
44
|
+
{
|
|
45
|
+
name: '准备参与者列表',
|
|
46
|
+
text: '从您的聊天记录、Excel 或社交网络中复制名字列表,并将其粘贴到文本框中。',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: '配置抽奖选项',
|
|
50
|
+
text: '选择您需要的获胜者人数,以及是否要过滤重复项或空白名字。',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: '启动“公平之手”',
|
|
54
|
+
text: '点击抽奖按钮。在揭晓获胜者之前,视觉动画将保持现场的紧张氛围。',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: '公布结果',
|
|
58
|
+
text: '复制获胜者的名字,以便在您的社交网络或直播聊天室中分享。',
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
63
|
+
'@context': 'https://schema.org',
|
|
64
|
+
'@type': 'FAQPage',
|
|
65
|
+
mainEntity: faqData.map((item) => ({
|
|
66
|
+
'@type': 'Question',
|
|
67
|
+
name: item.question,
|
|
68
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
69
|
+
})),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const howToSchema: WithContext<HowTo> = {
|
|
73
|
+
'@context': 'https://schema.org',
|
|
74
|
+
'@type': 'HowTo',
|
|
75
|
+
name: title,
|
|
76
|
+
description,
|
|
77
|
+
step: howToData.map((step, i) => ({
|
|
78
|
+
'@type': 'HowToStep',
|
|
79
|
+
position: i + 1,
|
|
80
|
+
name: step.name,
|
|
81
|
+
text: step.text,
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
86
|
+
'@context': 'https://schema.org',
|
|
87
|
+
'@type': 'SoftwareApplication',
|
|
88
|
+
name: title,
|
|
89
|
+
description,
|
|
90
|
+
applicationCategory: 'UtilityApplication',
|
|
91
|
+
operatingSystem: 'All',
|
|
92
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
93
|
+
inLanguage: 'zh',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const content: ToolLocaleContent<SorteoUI> = {
|
|
97
|
+
slug,
|
|
98
|
+
title,
|
|
99
|
+
description,
|
|
100
|
+
faqTitle: '常见问题',
|
|
101
|
+
faq: faqData,
|
|
102
|
+
bibliographyTitle: '技术参考',
|
|
103
|
+
bibliography: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Web Crypto API: getRandomValues()',
|
|
106
|
+
url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Fisher-Yates 洗牌算法',
|
|
110
|
+
url: 'https://zh.wikipedia.org/wiki/Fisher-Yates%E6%B4%97%E7%89%8C%E7%AE%97%E6%B3%95',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
howTo: howToData,
|
|
114
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema as any],
|
|
115
|
+
seo: [
|
|
116
|
+
{
|
|
117
|
+
type: 'title',
|
|
118
|
+
text: '在线随机名字抽取器与参与者列表',
|
|
119
|
+
level: 2,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: 'paragraph',
|
|
123
|
+
html: '想知道如何快速、安全且完全透明地进行在线随机抽奖吗?我们的免费<strong>名字抽取器</strong>工具是在几秒钟内随机选择获胜者的终极解决方案。它设计简单、直观且高效,非常适合任何需要数字“公平抽签”的应用场景。',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'paragraph',
|
|
127
|
+
html: '无论您是在管理社交网络上的竞赛,还是在直播频道进行大规模抽奖,亦或只是决定今天谁去倒垃圾,我们的随机选择器都能凭借现代加密算法保证绝对的公正性。<strong>没有操控,没有偏见,只有纯粹的随机性。</strong>'
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'title',
|
|
131
|
+
text: '应用场景',
|
|
132
|
+
level: 3,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'comparative',
|
|
136
|
+
columns: 2,
|
|
137
|
+
items: [
|
|
138
|
+
{
|
|
139
|
+
title: '社交媒体抽奖',
|
|
140
|
+
description: '非常适合 Instagram、Twitter (X) 或 Facebook 上的竞赛。只需从评论中复制名字并粘贴,即可选出公正的获胜者。工具会自动去除重复项。',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
title: 'Twitch / YouTube 直播',
|
|
144
|
+
description: '借助我们拥有流畅动画和集成音效的“直播间模式”,您可以直接在 OBS 中共享屏幕,在直播抽取获胜者的同时为观众呈现精彩的视觉效果。',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
title: '课堂与团队互动',
|
|
148
|
+
description: '教师和团队负责人可以使用它来随机分组、选择首位发言人或随机分配任务,确保过程完全透明且不带任何偏向。',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
title: '圣诞老人抽签与各类活动',
|
|
152
|
+
description: '通过瞬间随机选择名字,简化家庭聚会、办公室抽奖或圣诞老人抽签的组织工作,无需纸条或复杂的后勤准备。',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
type: 'title',
|
|
158
|
+
text: '为什么我们的工具与众不同?',
|
|
159
|
+
level: 3,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: 'list',
|
|
163
|
+
items: [
|
|
164
|
+
'<strong>真实加密:</strong> 我们使用浏览器的 Web Crypto API(W3C 标准),而非脆弱的伪随机生成器。每次抽奖在数学上都是公正的。',
|
|
165
|
+
'<strong>无存储:</strong> 您的数据永远不会离开浏览器。我们不出售列表、不分析您的特征、不存储任何内容。纯本地处理。',
|
|
166
|
+
'<strong>视觉设计:</strong> 影院模式和动画让每次抽奖都成为难忘的时刻。非常适合 OBS 捕获或直播。',
|
|
167
|
+
'<strong>去重处理:</strong> 自动检测重复的名字或变体(额外的空格、大小写等),以确保每个真实的人只被计算一次。',
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: 'title',
|
|
172
|
+
text: '抽奖步骤详解',
|
|
173
|
+
level: 3,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'list',
|
|
177
|
+
items: [
|
|
178
|
+
'<strong>第一步 - 输入参与者:</strong> 将名字列表粘贴到主文本框中。工具会自动将每个换行符识别为一个不同的参与者。有重复?没问题,工具会自动去除。',
|
|
179
|
+
'<strong>第二步 - 自定义:</strong> 在设置标签中,您可以开启倒计时以营造紧张感,开启五彩纸屑效果进行庆祝,或者开启“黑名单”以排除某些名字。',
|
|
180
|
+
'<strong>第三步 - 抽取!</strong> 点击主按钮,我们的引擎将生成加密安全的随机选择。获胜者将以清晰且令人难忘的方式展示。',
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: 'title',
|
|
185
|
+
text: '权重条目:赋予某些参与者优势',
|
|
186
|
+
level: 3,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'paragraph',
|
|
190
|
+
html: '想奖励您最忠实的订阅者或给某些参与者更多机会吗?我们的<strong>权重条目</strong>系统独一无二,允许您为任何名字分配“权重”或倍数,而无需多次书写。',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
type: 'tip',
|
|
194
|
+
title: '如何为名字分配权重',
|
|
195
|
+
html: '<p>使用星号 (*) 或 "x" 后跟参与次数。例如:</p><ul><li><strong>"张三 * 5"</strong> - 张三的竞争力相当于 5 个人</li><li><strong>"李四 x 10"</strong> - 李四获胜的几率增加 10 倍</li><li><strong>"王五"</strong> - 无符号 = 1 次常规参与</li></ul><p>这非常适合您想给 VIP 订阅者或特殊用户提供优势的抽奖活动。</p>',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'title',
|
|
199
|
+
text: '绝对的隐私与安全',
|
|
200
|
+
level: 3,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: 'paragraph',
|
|
204
|
+
html: '与其他在线工具不同,<strong>我们不存储您的数据</strong>。名字的所有处理和抽奖的执行都在您自己的浏览器本地完成。参与者列表绝不会通过网络传输,也不会保存在任何外部服务器上。',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
type: 'paragraph',
|
|
208
|
+
html: '<strong>这意味着什么?</strong> 参与者列表完全属于您。关闭标签页后,数据即刻消失。没有追踪 Cookie、没有用户画像、没有中央数据库。为您和参与抽奖的人提供最大的隐私保证。',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: 'title',
|
|
212
|
+
text: '数学透明性',
|
|
213
|
+
level: 3,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: 'paragraph',
|
|
217
|
+
html: '有人可能会问:“如果你操控结果怎么办?”答案很简单:<strong>我们做不到</strong>。抽奖代码是确定性且加密的。没有隐藏变量,没有“幕后黑手”。',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'paragraph',
|
|
221
|
+
html: '每位获胜者都是对您的确切列表应用 Fisher-Yates 洗牌算法后的直接结果,并使用了真实的加密熵。如果您想审计该过程,可以在 GitHub 上查看公开代码。',
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
ui: {
|
|
225
|
+
faqTitle: '常见问题',
|
|
226
|
+
bibliographyTitle: '技术参考',
|
|
227
|
+
title: '随机抽奖',
|
|
228
|
+
totalParticipants: '唯一参与者总数',
|
|
229
|
+
ready: '就绪',
|
|
230
|
+
participants: '参与者',
|
|
231
|
+
settings: '设置',
|
|
232
|
+
importFile: '导入文件',
|
|
233
|
+
clearAll: '清除全部',
|
|
234
|
+
placeholder: '在此键入或粘贴名字...\n张三\n李四\n@twitch_user',
|
|
235
|
+
onePerLine: '每行 1 位参与者',
|
|
236
|
+
lines: '行',
|
|
237
|
+
filters: '过滤器',
|
|
238
|
+
allowDuplicates: '允许重复',
|
|
239
|
+
winnerCount: '获胜者人数',
|
|
240
|
+
autoRemove: '自动移除获胜者',
|
|
241
|
+
blacklist: '黑名单 (排除)',
|
|
242
|
+
blacklistPlaceholder: '禁止的名字(每行一个)...',
|
|
243
|
+
blacklistInfo: '这些用户将不会进入抽奖。',
|
|
244
|
+
sceneEffects: '场景效果',
|
|
245
|
+
countdown: '倒计时 (3秒)',
|
|
246
|
+
confetti: '胜利纸屑',
|
|
247
|
+
zenMode: '禅模式 (隐藏面板)',
|
|
248
|
+
waitingParticipants: '等待参与者...',
|
|
249
|
+
winner: '获胜者',
|
|
250
|
+
reroll: '重新抽取',
|
|
251
|
+
history: '本次会话历史',
|
|
252
|
+
noWinnersYet: '暂无获胜者...',
|
|
253
|
+
startGiveaway: '开始抽奖',
|
|
254
|
+
studioHeader: 'LIVE STUDIO v2.0',
|
|
255
|
+
},
|
|
256
|
+
};
|
package/src/tool/sorteo/index.ts
CHANGED
|
@@ -16,6 +16,18 @@ export const sorteo: StreamingToolEntry<SorteoUI> = {
|
|
|
16
16
|
es: () => import('./i18n/es').then((m) => m.content),
|
|
17
17
|
en: () => import('./i18n/en').then((m) => m.content),
|
|
18
18
|
fr: () => import('./i18n/fr').then((m) => m.content),
|
|
19
|
+
de: () => import('./i18n/de').then((m) => m.content),
|
|
20
|
+
id: () => import('./i18n/id').then((m) => m.content),
|
|
21
|
+
it: () => import('./i18n/it').then((m) => m.content),
|
|
22
|
+
ja: () => import('./i18n/ja').then((m) => m.content),
|
|
23
|
+
ko: () => import('./i18n/ko').then((m) => m.content),
|
|
24
|
+
nl: () => import('./i18n/nl').then((m) => m.content),
|
|
25
|
+
pl: () => import('./i18n/pl').then((m) => m.content),
|
|
26
|
+
pt: () => import('./i18n/pt').then((m) => m.content),
|
|
27
|
+
ru: () => import('./i18n/ru').then((m) => m.content),
|
|
28
|
+
sv: () => import('./i18n/sv').then((m) => m.content),
|
|
29
|
+
tr: () => import('./i18n/tr').then((m) => m.content),
|
|
30
|
+
zh: () => import('./i18n/zh').then((m) => m.content),
|
|
19
31
|
},
|
|
20
32
|
};
|
|
21
33
|
|
package/src/tool/sorteo/ui.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export interface SorteoUI {
|
|
2
2
|
[key: string]: string;
|
|
3
|
+
faqTitle: string;
|
|
4
|
+
bibliographyTitle: string;
|
|
3
5
|
title: string;
|
|
4
6
|
totalParticipants: string;
|
|
5
7
|
ready: string;
|
|
@@ -27,4 +29,5 @@ export interface SorteoUI {
|
|
|
27
29
|
history: string;
|
|
28
30
|
noWinnersYet: string;
|
|
29
31
|
startGiveaway: string;
|
|
32
|
+
studioHeader: string;
|
|
30
33
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Icon } from 'astro-icon/components';
|
|
3
|
-
import {
|
|
4
|
-
import type { KnownLocale } from '../../types';
|
|
3
|
+
import type { TebasCheckUI } from './types';
|
|
5
4
|
import targetIps from './ips.json';
|
|
6
5
|
|
|
7
6
|
interface Props {
|
|
8
|
-
|
|
7
|
+
ui?: Record<string, string>;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
13
|
-
const ui = content?.ui;
|
|
10
|
+
const { ui: rawUi } = Astro.props;
|
|
11
|
+
const ui = (rawUi ?? {}) as TebasCheckUI;
|
|
14
12
|
---
|
|
15
13
|
|
|
16
14
|
<div
|